aboutsummaryrefslogtreecommitdiff
path: root/emulators
diff options
context:
space:
mode:
authorJuergen Lock <nox@FreeBSD.org>2014-04-18 10:53:51 +0000
committerJuergen Lock <nox@FreeBSD.org>2014-04-18 10:53:51 +0000
commitcf14e8bdd746039cc679bf4d0fc205ba4b95a2fb (patch)
tree3bcb58d0ad89f99a424a2a52c1c438790976da7d /emulators
parentf107703159f52960021a3a7a4255308eb359ed1d (diff)
downloadports-cf14e8bdd746039cc679bf4d0fc205ba4b95a2fb.tar.gz
ports-cf14e8bdd746039cc679bf4d0fc205ba4b95a2fb.zip
Notes
Diffstat (limited to 'emulators')
-rw-r--r--emulators/qemu-devel/Makefile41
-rw-r--r--emulators/qemu-devel/distinfo40
-rw-r--r--emulators/qemu-devel/files/extra-patch-38f8d5aaebdb4b1624bae86b374b5265c9f01b5429
-rw-r--r--emulators/qemu-devel/files/extra-patch-3d175d6ed5b809976662135369c639f53780ca5c38
-rw-r--r--emulators/qemu-devel/files/extra-patch-790d0ef625d22ff3f1a895d266a48e2bacd6377630291
-rw-r--r--emulators/qemu-devel/files/extra-patch-9ac2c49c734a49025fe1647ce84728d3988ea5d214
-rw-r--r--emulators/qemu-devel/files/extra-patch-a3129eea10f188bfd39ce83b18b25dcefbc5bffc53
-rw-r--r--emulators/qemu-devel/files/extra-patch-bsd-user-freebsd-os-proc.c11
-rw-r--r--emulators/qemu-devel/files/extra-patch-bsd-user-mips-target_arch_vmparam.h10
-rw-r--r--emulators/qemu-devel/files/extra-patch-bsd-user-mmap.c10
-rw-r--r--emulators/qemu-devel/files/extra-patch-bsd-user-syscall.c9
-rw-r--r--emulators/qemu-devel/files/extra-patch-c13_tls215
-rw-r--r--emulators/qemu-devel/files/extra-patch-fd7ec8e06cd1876ef478975f052ff64134d19c6c13
-rw-r--r--emulators/qemu-devel/files/extra-patch-inherit-interp_prefix10
-rw-r--r--emulators/qemu-devel/files/extra-patch-sysctl-0oldlen10
-rw-r--r--emulators/qemu-devel/files/extra-patch-sysctl-hw-availpages10
-rw-r--r--emulators/qemu-devel/files/patch-configure57
-rw-r--r--emulators/qemu-devel/files/patch-tcg-i386-tcg-target.c13
-rw-r--r--emulators/qemu-devel/files/pcap-patch12
-rw-r--r--emulators/qemu-devel/files/prepatch-configure10
20 files changed, 30564 insertions, 132 deletions
diff --git a/emulators/qemu-devel/Makefile b/emulators/qemu-devel/Makefile
index a4e221894c70..9b4bb19509c0 100644
--- a/emulators/qemu-devel/Makefile
+++ b/emulators/qemu-devel/Makefile
@@ -2,8 +2,7 @@
# $FreeBSD$
PORTNAME= qemu
-PORTVERSION= 1.7.1
-PORTREVISION= 5
+PORTVERSION= 2.0.0
CATEGORIES= emulators
MASTER_SITES= http://wiki.qemu.org/download/:release \
LOCAL/nox:snapshot
@@ -45,27 +44,14 @@ OPTIONS_DEFAULT=X11 GTK2 OPENGL GNUTLS SASL JPEG PNG CDROM_DMA CURL PCAP
.include <bsd.port.options.mk>
.if ${PORT_OPTIONS:MBSD_USER}
-PATCH_SITES= http://people.freebsd.org/~sson/qemu/qemu-bsd-user/
-PATCHFILES= \
- 0001-bsd-user-refresh-freebsd-system-call-numbers.patch \
- 0002-bsd-user-add-HOST_VARIANT_DIR-for-various-BSD-depend.patch \
- 0003-bsd-user-move-strace-OS-arch-dependent-code-to-host-.patch \
- 0004-bsd-user-move-arch-OS-dependent-code-out-of-main.c.patch \
- 0005-bsd-user-move-arch-OS-dependent-code-out-of-syscall..patch \
- 0006-bsd-user-add-support-for-freebsd-time-related-system.patch \
- 0007-bsd-user-add-support-for-freebsd-signal-related-syst.patch \
- 0008-bsd-user-move-arch-OS-dependent-code-out-of-elfload..patch \
- 0009-bsd-user-add-support-for-freebsd-process-related-sys.patch \
- 0010-bsd-user-add-support-for-file-system-related-system-.patch \
- 0011-bsd-user-add-support-for-stat-dir-and-fcntl-related-.patch \
- 0012-bsd-user-add-support-for-memory-management-related-s.patch \
- 0013-bsd-user-add-support-for-socket-related-system-calls.patch \
- 0014-bsd-user-add-support-for-thread-related-system-calls.patch \
- 0015-bsd-user-add-support-for-the-ioctl-system-call.patch \
- 0016-bsd-user-add-support-for-extattr-and-ACL-related-sys.patch \
- 0017-bsd-user-add-support-for-miscellaneous-system-calls.patch \
- 0018-bsd-user-add-arm-mips-and-mips64-options-to-configur.patch
-PATCH_DIST_STRIP= -p1
+EXTRA_PATCHES+= ${FILESDIR}/extra-patch-790d0ef625d22ff3f1a895d266a48e2bacd63776
+EXTRA_PATCHES+= ${FILESDIR}/extra-patch-3d175d6ed5b809976662135369c639f53780ca5c
+EXTRA_PATCHES+= ${FILESDIR}/extra-patch-a3129eea10f188bfd39ce83b18b25dcefbc5bffc
+EXTRA_PATCHES+= ${FILESDIR}/extra-patch-fd7ec8e06cd1876ef478975f052ff64134d19c6c
+EXTRA_PATCHES+= ${FILESDIR}/extra-patch-9ac2c49c734a49025fe1647ce84728d3988ea5d2
+EXTRA_PATCHES+= ${FILESDIR}/extra-patch-38f8d5aaebdb4b1624bae86b374b5265c9f01b54
+EXTRA_PATCHES+= ${FILESDIR}/extra-patch-c13_tls2
+#
EXTRA_PATCHES+= ${FILESDIR}/extra-patch-bsd-user-freebsd-os-proc.c
EXTRA_PATCHES+= ${FILESDIR}/extra-patch-05ee8495804599b52a88eb36b13ea9c06b3207cd
EXTRA_PATCHES+= ${FILESDIR}/extra-patch-bsd-user-mips-target_arch_vmparam.h
@@ -97,7 +83,7 @@ CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu
CONFIGURE_ARGS+= --disable-bsd-user
.else
.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,moxie-softmmu,i386-bsd-user,sparc-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user
+CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,aarch64-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,moxie-softmmu,i386-bsd-user,sparc-bsd-user,arm-bsd-user,mips-bsd-user,mipsel-bsd-user
.endif
.endif
.endif
@@ -144,7 +130,7 @@ USE_SDL= sdl
.endif
.if empty(PORT_OPTIONS:MGTK2)
-CONFIGURE_ARGS+= --disable-gtk
+CONFIGURE_ARGS+= --disable-gtk --disable-vte
PLIST_SUB+= GTK2="@comment "
.else
USE_GNOME+= gtk20 vte
@@ -241,11 +227,6 @@ MAKE_ENV+= COMPILER_PATH=${LOCALBASE}/bin
CONFIGURE_ARGS+= --python=${PYTHON_CMD}
-.if ${PORT_OPTIONS:MBSD_USER}
-pre-patch:
- @cd ${WRKSRC} && ${PATCH} --quiet < ${FILESDIR}/prepatch-configure
-.endif
-
# -lprocstat actually only _needs_ -lelf after r249666 or r250870 (MFC)
# but it shouldn't matter much
post-patch:
diff --git a/emulators/qemu-devel/distinfo b/emulators/qemu-devel/distinfo
index 81eeabf70792..71faa8a40180 100644
--- a/emulators/qemu-devel/distinfo
+++ b/emulators/qemu-devel/distinfo
@@ -1,38 +1,2 @@
-SHA256 (qemu/1.7.1/qemu-1.7.1.tar.bz2) = d68942a004222eebae5d156ceefb308fabd98edb282d1dde49ec810bbf01bef4
-SIZE (qemu/1.7.1/qemu-1.7.1.tar.bz2) = 12246206
-SHA256 (qemu/1.7.1/0001-bsd-user-refresh-freebsd-system-call-numbers.patch) = 15fa3f286ae03636c9340de0b44ec4fc47e428025f103382a578029db45ec252
-SIZE (qemu/1.7.1/0001-bsd-user-refresh-freebsd-system-call-numbers.patch) = 36542
-SHA256 (qemu/1.7.1/0002-bsd-user-add-HOST_VARIANT_DIR-for-various-BSD-depend.patch) = 021f8c1fdba448c8eeb7a9f8035b8a47b1f463a59ee7da60d733bd63c2924b13
-SIZE (qemu/1.7.1/0002-bsd-user-add-HOST_VARIANT_DIR-for-various-BSD-depend.patch) = 2730
-SHA256 (qemu/1.7.1/0003-bsd-user-move-strace-OS-arch-dependent-code-to-host-.patch) = b0b08af1a4d6e7e660290c9f0293d7ad486c51df8fce29abed9db76143317d8a
-SIZE (qemu/1.7.1/0003-bsd-user-move-strace-OS-arch-dependent-code-to-host-.patch) = 50756
-SHA256 (qemu/1.7.1/0004-bsd-user-move-arch-OS-dependent-code-out-of-main.c.patch) = 184336d1e8a6fabfa4fc6043603ab4f373d1ae80aefd7c57ba23cc36038b81da
-SIZE (qemu/1.7.1/0004-bsd-user-move-arch-OS-dependent-code-out-of-main.c.patch) = 143116
-SHA256 (qemu/1.7.1/0005-bsd-user-move-arch-OS-dependent-code-out-of-syscall..patch) = 352b624cb09223a2c2df6281211719e20964829b5d776a18a8a0b5fe405ac9e3
-SIZE (qemu/1.7.1/0005-bsd-user-move-arch-OS-dependent-code-out-of-syscall..patch) = 44814
-SHA256 (qemu/1.7.1/0006-bsd-user-add-support-for-freebsd-time-related-system.patch) = fa6a24c90f451ba087964c3089b887cc97ef4aec66a251dd0b67279f66134737
-SIZE (qemu/1.7.1/0006-bsd-user-add-support-for-freebsd-time-related-system.patch) = 75063
-SHA256 (qemu/1.7.1/0007-bsd-user-add-support-for-freebsd-signal-related-syst.patch) = e4d78570ab787be5131a9336d06c51309a684a02b612099929f0bea728c99225
-SIZE (qemu/1.7.1/0007-bsd-user-add-support-for-freebsd-signal-related-syst.patch) = 100195
-SHA256 (qemu/1.7.1/0008-bsd-user-move-arch-OS-dependent-code-out-of-elfload..patch) = 6a5083c5257aea2da050cdf47a261b4e883a7b4e8a1410dd7dae4b1499f600c8
-SIZE (qemu/1.7.1/0008-bsd-user-move-arch-OS-dependent-code-out-of-elfload..patch) = 93309
-SHA256 (qemu/1.7.1/0009-bsd-user-add-support-for-freebsd-process-related-sys.patch) = 7e5e99ef2279c3023d21b9540eb9ad9355cd0010dd402cd60ab3abe6c40cb36f
-SIZE (qemu/1.7.1/0009-bsd-user-add-support-for-freebsd-process-related-sys.patch) = 60141
-SHA256 (qemu/1.7.1/0010-bsd-user-add-support-for-file-system-related-system-.patch) = 52f97f394b5c75778e4f003de1033896fdc07c235289a9e91a8771e75bb9fd18
-SIZE (qemu/1.7.1/0010-bsd-user-add-support-for-file-system-related-system-.patch) = 43516
-SHA256 (qemu/1.7.1/0011-bsd-user-add-support-for-stat-dir-and-fcntl-related-.patch) = 5d25f3363080806a939cc985c9866c409006b35840a81f8d3c74f2cb9451ed31
-SIZE (qemu/1.7.1/0011-bsd-user-add-support-for-stat-dir-and-fcntl-related-.patch) = 31292
-SHA256 (qemu/1.7.1/0012-bsd-user-add-support-for-memory-management-related-s.patch) = f9e39e7138ad8c995255a4300b6887fce468296f61467445d3d2438cb6e1a761
-SIZE (qemu/1.7.1/0012-bsd-user-add-support-for-memory-management-related-s.patch) = 37395
-SHA256 (qemu/1.7.1/0013-bsd-user-add-support-for-socket-related-system-calls.patch) = 3e9f586a7327424d449c5a7c9cd7a589d8b14091bbe860cfe00a518bd1f6800c
-SIZE (qemu/1.7.1/0013-bsd-user-add-support-for-socket-related-system-calls.patch) = 46894
-SHA256 (qemu/1.7.1/0014-bsd-user-add-support-for-thread-related-system-calls.patch) = f33d86896466ba39484715253ba9284d6c335b4e0e635150507bad63ef19e113
-SIZE (qemu/1.7.1/0014-bsd-user-add-support-for-thread-related-system-calls.patch) = 67546
-SHA256 (qemu/1.7.1/0015-bsd-user-add-support-for-the-ioctl-system-call.patch) = 90407a8e312ac5f4b3524cd5f65274baea49c4addf04a4614ce356e069983ab3
-SIZE (qemu/1.7.1/0015-bsd-user-add-support-for-the-ioctl-system-call.patch) = 77683
-SHA256 (qemu/1.7.1/0016-bsd-user-add-support-for-extattr-and-ACL-related-sys.patch) = b74903bfa42718edf4db21a2d746ab2c9548694c6dd6a270ea7c6885405505ec
-SIZE (qemu/1.7.1/0016-bsd-user-add-support-for-extattr-and-ACL-related-sys.patch) = 43940
-SHA256 (qemu/1.7.1/0017-bsd-user-add-support-for-miscellaneous-system-calls.patch) = 6238ab7325c95b64544e7e72e7c45e44d4625a2e64851248dbb621b86ac7ed0d
-SIZE (qemu/1.7.1/0017-bsd-user-add-support-for-miscellaneous-system-calls.patch) = 58081
-SHA256 (qemu/1.7.1/0018-bsd-user-add-arm-mips-and-mips64-options-to-configur.patch) = 694159e25187159709d449741446cc3218d31ea7eee47dde4946e8505d48a798
-SIZE (qemu/1.7.1/0018-bsd-user-add-arm-mips-and-mips64-options-to-configur.patch) = 2341
+SHA256 (qemu/2.0.0/qemu-2.0.0.tar.bz2) = 60cc1aa0cad39cec891f970bed60ca8a484f071adad4943123599ac223543a3b
+SIZE (qemu/2.0.0/qemu-2.0.0.tar.bz2) = 12839647
diff --git a/emulators/qemu-devel/files/extra-patch-38f8d5aaebdb4b1624bae86b374b5265c9f01b54 b/emulators/qemu-devel/files/extra-patch-38f8d5aaebdb4b1624bae86b374b5265c9f01b54
new file mode 100644
index 000000000000..3de6319ed4f6
--- /dev/null
+++ b/emulators/qemu-devel/files/extra-patch-38f8d5aaebdb4b1624bae86b374b5265c9f01b54
@@ -0,0 +1,29 @@
+diff --git a/bsd-user/freebsd/os-thread.c b/bsd-user/freebsd/os-thread.c
+index 6bf2a9f..bcd2445 100644
+--- a/bsd-user/freebsd/os-thread.c
++++ b/bsd-user/freebsd/os-thread.c
+@@ -899,11 +899,13 @@ abi_long do_freebsd_thr_new(CPUArchState *env,
+ pthread_attr_t attr;
+ TaskState *ts;
+ CPUArchState *new_env;
++ CPUState *new_cpu;
+ struct target_freebsd_thr_param *target_param;
+ abi_ulong target_rtp_addr;
+ struct target_freebsd_rtprio *target_rtp;
+ struct rtprio *rtp_ptr, rtp;
+- TaskState *parent_ts = (TaskState *)env->opaque;
++ CPUState *parent_cpu = ENV_GET_CPU(env);
++ TaskState *parent_ts = parent_cpu->opaque;
+ sigset_t sigmask;
+ struct sched_param sched_param;
+ int sched_policy;
+@@ -948,7 +950,8 @@ abi_long do_freebsd_thr_new(CPUArchState *env,
+
+ /* init regs that differ from the parent thread. */
+ target_cpu_clone_regs(new_env, info.param.stack_base);
+- new_env->opaque = ts;
++ new_cpu = ENV_GET_CPU(new_env);
++ new_cpu->opaque = ts;
+ ts->bprm = parent_ts->bprm;
+ ts->info = parent_ts->info;
+
diff --git a/emulators/qemu-devel/files/extra-patch-3d175d6ed5b809976662135369c639f53780ca5c b/emulators/qemu-devel/files/extra-patch-3d175d6ed5b809976662135369c639f53780ca5c
new file mode 100644
index 000000000000..9272f46aa42f
--- /dev/null
+++ b/emulators/qemu-devel/files/extra-patch-3d175d6ed5b809976662135369c639f53780ca5c
@@ -0,0 +1,38 @@
+diff --git a/bsd-user/main.c b/bsd-user/main.c
+index f27fcbc..16a0590 100644
+--- a/bsd-user/main.c
++++ b/bsd-user/main.c
+@@ -272,6 +272,7 @@ void init_task_state(TaskState *ts)
+ CPUArchState *cpu_copy(CPUArchState *env)
+ {
+ CPUArchState *new_env = cpu_init(cpu_model);
++ CPUState *cpu;
+ #if defined(TARGET_HAS_ICE)
+ CPUBreakpoint *bp;
+ CPUWatchpoint *wp;
+@@ -281,18 +282,19 @@ CPUArchState *cpu_copy(CPUArchState *env)
+ cpu_reset(ENV_GET_CPU(new_env));
+
+ memcpy(new_env, env, sizeof(CPUArchState));
++ cpu = ENV_GET_CPU(env);
+
+ /* Clone all break/watchpoints.
+ Note: Once we support ptrace with hw-debug register access, make sure
+ BP_CPU break/watchpoints are handled correctly on clone. */
+- QTAILQ_INIT(&env->breakpoints);
+- QTAILQ_INIT(&env->watchpoints);
++ QTAILQ_INIT(&cpu->breakpoints);
++ QTAILQ_INIT(&cpu->watchpoints);
+ #if defined(TARGET_HAS_ICE)
+- QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+- cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
++ QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
++ cpu_breakpoint_insert(cpu, bp->pc, bp->flags, NULL);
+ }
+- QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
+- cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
++ QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
++ cpu_watchpoint_insert(cpu, wp->vaddr, (~wp->len_mask) + 1,
+ wp->flags, NULL);
+ }
+ #endif
diff --git a/emulators/qemu-devel/files/extra-patch-790d0ef625d22ff3f1a895d266a48e2bacd63776 b/emulators/qemu-devel/files/extra-patch-790d0ef625d22ff3f1a895d266a48e2bacd63776
new file mode 100644
index 000000000000..15043fae944d
--- /dev/null
+++ b/emulators/qemu-devel/files/extra-patch-790d0ef625d22ff3f1a895d266a48e2bacd63776
@@ -0,0 +1,30291 @@
+diff --git a/Makefile.target b/Makefile.target
+index ba12340..9e9a913 100644
+--- a/Makefile.target
++++ b/Makefile.target
+@@ -99,10 +99,11 @@ endif #CONFIG_LINUX_USER
+
+ ifdef CONFIG_BSD_USER
+
+-QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ABI_DIR)
++QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ABI_DIR) \
++ -I$(SRC_PATH)/bsd-user/$(HOST_VARIANT_DIR)
+
+ 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/Makefile.objs b/bsd-user/Makefile.objs
+index 5e77f57..ab025a4 100644
+--- a/bsd-user/Makefile.objs
++++ b/bsd-user/Makefile.objs
+@@ -1,2 +1,6 @@
+ obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
+- uaccess.o
++ uaccess.o bsd-ioctl.o bsd-mem.o bsd-misc.o bsd-proc.o bsd-socket.o \
++ $(HOST_VARIANT_DIR)/os-extattr.o $(HOST_VARIANT_DIR)/os-proc.o \
++ $(HOST_VARIANT_DIR)/os-socket.o $(HOST_VARIANT_DIR)/os-stat.o \
++ $(HOST_VARIANT_DIR)/os-sys.o $(HOST_VARIANT_DIR)/os-thread.o \
++ $(HOST_VARIANT_DIR)/os-time.o $(TARGET_ABI_DIR)/target_arch_cpu.o
+diff --git a/bsd-user/arm/syscall.h b/bsd-user/arm/syscall.h
+new file mode 100644
+index 0000000..bc3d6e6
+--- /dev/null
++++ b/bsd-user/arm/syscall.h
+@@ -0,0 +1,36 @@
++#ifndef __ARCH_SYSCALL_H_
++#define __ARCH_SYSCALL_H_
++
++struct target_pt_regs {
++ abi_long uregs[17];
++};
++
++#define ARM_cpsr uregs[16]
++#define ARM_pc uregs[15]
++#define ARM_lr uregs[14]
++#define ARM_sp uregs[13]
++#define ARM_ip uregs[12]
++#define ARM_fp uregs[11]
++#define ARM_r10 uregs[10]
++#define ARM_r9 uregs[9]
++#define ARM_r8 uregs[8]
++#define ARM_r7 uregs[7]
++#define ARM_r6 uregs[6]
++#define ARM_r5 uregs[5]
++#define ARM_r4 uregs[4]
++#define ARM_r3 uregs[3]
++#define ARM_r2 uregs[2]
++#define ARM_r1 uregs[1]
++#define ARM_r0 uregs[0]
++
++#define ARM_SYSCALL_BASE 0 /* XXX: FreeBSD only */
++
++#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
++
++#define TARGET_HW_MACHINE "arm"
++#define TARGET_HW_MACHINE_ARCH "armv6"
++
++#endif /* !__ARCH_SYSCALL_H_ */
+diff --git a/bsd-user/arm/target_arch.h b/bsd-user/arm/target_arch.h
+new file mode 100644
+index 0000000..b5c5ddb
+--- /dev/null
++++ b/bsd-user/arm/target_arch.h
+@@ -0,0 +1,10 @@
++
++#ifndef _TARGET_ARCH_H_
++#define _TARGET_ARCH_H_
++
++#include "qemu.h"
++
++void target_cpu_set_tls(CPUARMState *env, target_ulong newtls);
++target_ulong target_cpu_get_tls(CPUARMState *env);
++
++#endif /* !_TARGET_ARCH_H_ */
+diff --git a/bsd-user/arm/target_arch_cpu.c b/bsd-user/arm/target_arch_cpu.c
+new file mode 100644
+index 0000000..d94a32a
+--- /dev/null
++++ b/bsd-user/arm/target_arch_cpu.c
+@@ -0,0 +1,27 @@
++/*
++ * arm cpu related code
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#include "target_arch.h"
++
++void target_cpu_set_tls(CPUARMState *env, target_ulong newtls)
++{
++ env->cp15.c13_tls2 = newtls;
++}
++
++target_ulong target_cpu_get_tls(CPUARMState *env)
++{
++ return (env->cp15.c13_tls2);
++}
+diff --git a/bsd-user/arm/target_arch_cpu.h b/bsd-user/arm/target_arch_cpu.h
+new file mode 100644
+index 0000000..3eeb34a
+--- /dev/null
++++ b/bsd-user/arm/target_arch_cpu.h
+@@ -0,0 +1,375 @@
++/*
++ * arm cpu init and loop
++ *
++ * Olivier Houchard
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _TARGET_ARCH_CPU_H_
++#define _TARGET_ARCH_CPU_H_
++
++#include "target_arch.h"
++
++// #define DEBUG_PRINTF(...) fprintf(stderr, __VA_ARGS__)
++#define DEBUG_PRINTF(...)
++
++#define TARGET_DEFAULT_CPU_MODEL "any"
++
++#define TARGET_CPU_RESET(env)
++
++static inline void target_cpu_init(CPUARMState *env,
++ struct target_pt_regs *regs)
++{
++ int i;
++
++ cpsr_write(env, regs->uregs[16], 0xffffffff);
++ for (i = 0; i < 16; i++) {
++ env->regs[i] = regs->uregs[i];
++ }
++}
++
++static inline 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;
++}
++
++static inline void target_cpu_loop(CPUARMState *env)
++{
++ int trapnr;
++ target_siginfo_t info;
++ unsigned int n;
++ uint32_t addr;
++ CPUState *cs = CPU(arm_env_get_cpu(env));
++
++ for (;;) {
++ DEBUG_PRINTF("CPU_LOOPING\n");
++ cpu_exec_start(cs);
++ DEBUG_PRINTF("EXECUTING...\n");
++ trapnr = cpu_arm_exec(env);
++ DEBUG_PRINTF("trapnr %d\n", trapnr);
++ cpu_exec_end(cs);
++ switch (trapnr) {
++ case EXCP_UDEF:
++ {
++ /* See arm/arm/undefined.c undefinedinstruction(); */
++ info.si_addr = env->regs[15];
++
++ /*
++ * Make sure the PC is correctly aligned. (It should
++ * be.)
++ */
++ if ((info.si_addr & 3) != 0) {
++ info.si_signo = SIGILL;
++ info.si_errno = 0;
++ info.si_code = TARGET_ILL_ILLADR;
++ queue_signal(env, info.si_signo, &info);
++ } else {
++ int rc = 0;
++#ifdef NOT_YET
++ uint32_t opcode;
++
++ /*
++ * Get the opcode.
++ *
++ * FIXME - what to do if get_user() fails?
++ */
++ get_user_u32(opcode, env->regs[15]);
++
++ /* Check the opcode with CP handlers we may have. */
++ rc = EmulateAll(opcode, &ts-fpa, env);
++#endif /* NOT_YET */
++ if (rc == 0) {
++ /* illegal instruction */
++ info.si_signo = SIGILL;
++ info.si_errno = 0;
++ info.si_code = TARGET_ILL_ILLOPC;
++ queue_signal(env, info.si_signo, &info);
++ }
++ }
++ }
++ break;
++ case EXCP_SWI:
++ case EXCP_BKPT:
++ {
++ unsigned int insn;
++#ifdef FREEBSD_ARM_OABI
++ env->eabi = 0;
++#else
++ env->eabi = 1;
++#endif
++ /*
++ * system call
++ * See arm/arm/trap.c cpu_fetch_syscall_args()
++ */
++ if (trapnr == EXCP_BKPT) {
++ if (env->thumb) {
++ if (env->eabi) {
++ n = env->regs[7];
++ } else {
++ /* FIXME - what to do if get_user() fails? */
++ get_user_u16(insn, env->regs[15]);
++ n = insn & 0xff;
++ }
++ env->regs[15] += 2;
++ } else {
++ if (env->eabi) {
++ n = env->regs[7];
++ } else {
++ /* FIXME - what to do if get_user() fails? */
++ get_user_u32(insn, env->regs[15]);
++ n = (insn & 0xf) | ((insn >> 4) & 0xff0);
++ }
++ env->regs[15] += 4;
++ }
++ } else { /* trapnr != EXCP_BKPT */
++ if (env->thumb) {
++ if (env->eabi) {
++ n = env->regs[7];
++ } else {
++ /* FIXME - what to do if get_user() fails? */
++ get_user_u16(insn, env->regs[15] - 2);
++ n = insn & 0xff;
++ }
++ } else {
++ if (env->eabi) {
++ n = env->regs[7];
++ } else {
++ /* FIXME - what to do if get_user() fails? */
++ get_user_u32(insn, env->regs[15] - 4);
++ n = insn & 0xffffff;
++ }
++ }
++ }
++ DEBUG_PRINTF("AVANT CALL %d\n", n);
++ if (bsd_type == target_freebsd) {
++ int ret;
++ abi_ulong params = get_sp_from_cpustate(env);
++ int32_t syscall_nr = n;
++ int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
++
++ /* See arm/arm/trap.c cpu_fetch_syscall_args() */
++ if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
++ syscall_nr = env->regs[0];
++ arg1 = env->regs[1];
++ arg2 = env->regs[2];
++ arg3 = env->regs[3];
++ get_user_s32(arg4, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg5, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg6, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg7, params);
++ arg8 = 0;
++ } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
++#ifdef TARGET_WORDS_BIGENDIAN
++ syscall_nr = env->regs[1];
++#else
++ syscall_nr = env->regs[0];
++#endif
++ arg1 = env->regs[2];
++ arg2 = env->regs[3];
++ get_user_s32(arg3, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg4, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg5, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg6, params);
++ arg7 = 0;
++ arg8 = 0;
++ } else {
++ arg1 = env->regs[0];
++ arg2 = env->regs[1];
++ arg3 = env->regs[2];
++ arg4 = env->regs[3];
++ get_user_s32(arg5, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg6, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg7, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg8, params);
++ }
++ ret = do_freebsd_syscall(env, syscall_nr, arg1, arg2, arg3,
++ arg4, arg5, arg6, arg7, arg8);
++ /*
++ * 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 if (bsd_type == target_openbsd)... */
++ else {
++ fprintf(stderr, "qemu: bsd_type (= %d) syscall "
++ "not supported\n", bsd_type);
++ }
++ DEBUG_PRINTF("APRES CALL\n");
++ }
++ break;
++ case EXCP_INTERRUPT:
++ /* just indicate that signals should be handled asap */
++ break;
++ case EXCP_PREFETCH_ABORT:
++ /* See arm/arm/trap.c prefetch_abort_handler() */
++ addr = env->cp15.c6_insn;
++ goto do_segv;
++ case EXCP_DATA_ABORT:
++ /* See arm/arm/trap.c data_abort_handler() */
++ addr = env->cp15.c6_data;
++ do_segv:
++ {
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ /* XXX: check env->error_code */
++ info.si_code = 0;
++ info.si_addr = addr;
++ queue_signal(env, info.si_signo, &info);
++ }
++ break;
++ case EXCP_DEBUG:
++ {
++ int sig;
++
++ sig = gdb_handlesig(cs, 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;
++ /* XXX case EXCP_KERNEL_TRAP: */
++ case EXCP_STREX:
++ if (do_strex(env)) {
++ addr = env->cp15.c6_data;
++ goto do_segv;
++ }
++ break;
++ default:
++ fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
++ trapnr);
++ cpu_dump_state(cs, stderr, fprintf, 0);
++ abort();
++ } /* switch() */
++ process_pending_signals(env);
++ } /* for (;;) */
++}
++
++static inline void target_cpu_clone_regs(CPUARMState *env, target_ulong newsp)
++{
++ if (newsp)
++ env->regs[13] = newsp;
++ env->regs[0] = 0;
++}
++
++static inline void target_cpu_reset(CPUArchState *cpu)
++{
++}
++
++#endif /* !_TARGET_ARCH_CPU_H */
+diff --git a/bsd-user/arm/target_arch_elf.h b/bsd-user/arm/target_arch_elf.h
+new file mode 100644
+index 0000000..c408cea
+--- /dev/null
++++ b/bsd-user/arm/target_arch_elf.h
+@@ -0,0 +1,54 @@
++/*
++ * arm ELF definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_ELF_H_
++#define _TARGET_ARCH_ELF_H_
++
++#define ELF_START_MMAP 0x80000000
++
++#define elf_check_arch(x) ( (x) == EM_ARM )
++
++#define ELF_CLASS ELFCLASS32
++#ifdef TARGET_WORDS_BIGENDIAN
++#define ELF_DATA ELFDATA2MSB
++#else
++#define ELF_DATA ELFDATA2LSB
++#endif
++#define ELF_ARCH EM_ARM
++
++#define USE_ELF_CORE_DUMP
++#define ELF_EXEC_PAGESIZE 4096
++
++enum
++{
++ ARM_HWCAP_ARM_SWP = 1 << 0,
++ ARM_HWCAP_ARM_HALF = 1 << 1,
++ ARM_HWCAP_ARM_THUMB = 1 << 2,
++ ARM_HWCAP_ARM_26BIT = 1 << 3,
++ ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
++ ARM_HWCAP_ARM_FPA = 1 << 5,
++ ARM_HWCAP_ARM_VFP = 1 << 6,
++ ARM_HWCAP_ARM_EDSP = 1 << 7,
++};
++
++#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \
++ | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \
++ | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP)
++
++
++#endif /* _TARGET_ARCH_ELF_H_ */
+diff --git a/bsd-user/arm/target_arch_signal.h b/bsd-user/arm/target_arch_signal.h
+new file mode 100644
+index 0000000..048bd4f
+--- /dev/null
++++ b/bsd-user/arm/target_arch_signal.h
+@@ -0,0 +1,257 @@
++/*
++ * arm signal definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_SIGNAL_H_
++#define _TARGET_ARCH_SIGNAL_H_
++
++#include "cpu.h"
++
++#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
++#define TARGET__NGREG 17
++/* 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_INSN_SIZE 4 /* arm instruction size */
++
++/* Size of the signal trampolin code. See _sigtramp(). */
++#define TARGET_SZSIGCODE ((abi_ulong)(8 * TARGET_INSN_SIZE))
++
++/* compare to arm/include/_limits.h */
++#define TARGET_MINSIGSTKSZ (1024 * 4) /* min sig stack size */
++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) /* recommended size */
++
++/* arm/arm/machdep.c */
++#define TARGET_MC_GET_CLEAR_RET 0x0001
++#define TARGET_MC_ADD_MAGIC 0x0002
++#define TARGET_MC_SET_ONSTACK 0x0004
++
++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 {
++ 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 struct {
++ uint32_t __vfp_fpscr;
++ uint32_t __vfp_fstmx[33];
++ uint32_t __vfp_fpsid;
++} target__vfpregset_t;
++
++typedef struct target_mcontext {
++ 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;
++ 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_siginfo_t sf_si; /* saved siginfo */
++ target_ucontext_t sf_uc; /* saved ucontext */
++};
++
++
++/* compare to sys/arm/include/frame.h */
++struct target_trapframe {
++ abi_ulong tf_spsr; /* Zero on arm26 */
++ abi_ulong tf_r0;
++ abi_ulong tf_r1;
++ abi_ulong tf_r2;
++ abi_ulong tf_r3;
++ abi_ulong tf_r4;
++ abi_ulong tf_r5;
++ abi_ulong tf_r6;
++ abi_ulong tf_r7;
++ abi_ulong tf_r8;
++ abi_ulong tf_r9;
++ abi_ulong tf_r10;
++ abi_ulong tf_r11;
++ abi_ulong tf_r12;
++ abi_ulong tf_usr_sp;
++ abi_ulong tf_usr_lr;
++ abi_ulong tf_svc_sp; /* Not used on arm26 */
++ abi_ulong tf_svc_lr; /* Not used on arm26 */
++ abi_ulong tf_pc;
++};
++
++/*
++ * Compare to arm/arm/machdep.c sendsig()
++ * Assumes that target stack frame memory is locked.
++ */
++static inline abi_long
++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()
++ * Assumes that the memory is locked if mcp points to user memory.
++ */
++static inline abi_long get_mcontext(CPUARMState *regs, target_mcontext_t *mcp,
++ int flags)
++{
++ int err = 0;
++ uint32_t *gr = mcp->__gregs;
++
++
++ if (flags & TARGET_MC_GET_CLEAR_RET) {
++ gr[TARGET_REG_R0] = 0;
++ } else {
++ gr[TARGET_REG_R0] = tswap32(regs->regs[0]);
++ }
++
++ 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(cpsr_read(regs));
++
++ return err;
++}
++
++/* Compare to arm/arm/machdep.c set_mcontext() */
++static inline abi_long set_mcontext(CPUARMState *regs, target_mcontext_t *mcp,
++ int srflag)
++{
++ 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]);
++
++ regs->regs[13] = tswap32(gr[TARGET_REG_SP]);
++ regs->regs[14] = tswap32(gr[TARGET_REG_LR]);
++ regs->regs[15] = tswap32(gr[TARGET_REG_PC]);
++ 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 target_sf, abi_ulong *target_uc)
++{
++ uint32_t cpsr = cpsr_read(regs);
++
++ *target_uc = 0;
++
++ if ((cpsr & CPSR_M) != ARM_CPU_MODE_USR ||
++ (cpsr & (CPSR_I | CPSR_F)) != 0) {
++ return -TARGET_EINVAL;
++ }
++
++ *target_uc = target_sf + offsetof(struct target_sigframe, sf_uc);
++
++ return 0;
++}
++
++
++#endif /* !_TARGET_ARCH_SIGNAL_H_ */
+diff --git a/bsd-user/arm/target_arch_sigtramp.h b/bsd-user/arm/target_arch_sigtramp.h
+new file mode 100644
+index 0000000..98dc313
+--- /dev/null
++++ b/bsd-user/arm/target_arch_sigtramp.h
+@@ -0,0 +1,33 @@
++
++#ifndef _TARGET_ARCH_SIGTRAMP_H_
++#define _TARGET_ARCH_SIGTRAMP_H_
++
++/* Compare to arm/arm/locore.S ENTRY_NP(sigcode) */
++static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
++ unsigned 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);
++}
++#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
+diff --git a/bsd-user/arm/target_arch_sysarch.h b/bsd-user/arm/target_arch_sysarch.h
+new file mode 100644
+index 0000000..96d617a
+--- /dev/null
++++ b/bsd-user/arm/target_arch_sysarch.h
+@@ -0,0 +1,78 @@
++/*
++ * arm sysarch() system call emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __ARCH_SYSARCH_H_
++#define __ARCH_SYSARCH_H_
++
++#include "syscall.h"
++#include "target_arch.h"
++
++static inline abi_long do_freebsd_arch_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:
++ target_cpu_set_tls(env, parms);
++ break;
++
++ case TARGET_FREEBSD_ARM_GET_TP:
++ ret = target_cpu_get_tls(env);
++ break;
++
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++ return ret;
++}
++
++static inline void do_freebsd_arch_print_sysarch(
++ const struct syscallname *name, abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
++{
++
++ switch (arg1) {
++ case TARGET_FREEBSD_ARM_SYNC_ICACHE:
++ gemu_log("%s(ARM_SYNC_ICACHE, ...)", name->name);
++ break;
++
++ case TARGET_FREEBSD_ARM_DRAIN_WRITEBUF:
++ gemu_log("%s(ARM_DRAIN_WRITEBUF, ...)", name->name);
++ break;
++
++ case TARGET_FREEBSD_ARM_SET_TP:
++ gemu_log("%s(ARM_SET_TP, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2);
++ break;
++
++ case TARGET_FREEBSD_ARM_GET_TP:
++ gemu_log("%s(ARM_GET_TP, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2);
++ break;
++
++ default:
++ gemu_log("UNKNOWN OP: %d, " TARGET_ABI_FMT_lx ")", (int)arg1, arg2);
++ }
++}
++
++#endif /*!__ARCH_SYSARCH_H_ */
+diff --git a/bsd-user/arm/target_arch_thread.h b/bsd-user/arm/target_arch_thread.h
+new file mode 100644
+index 0000000..e69f612d
+--- /dev/null
++++ b/bsd-user/arm/target_arch_thread.h
+@@ -0,0 +1,67 @@
++/*
++ * arm thread support
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_THREAD_H_
++#define _TARGET_ARCH_THREAD_H_
++
++/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */
++static inline void target_thread_set_upcall(CPUARMState *regs, abi_ulong entry,
++ abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
++{
++ abi_ulong sp;
++
++ /*
++ * Make sure the stack is properly aligned.
++ * arm/include/param.h (STACKLIGN() macro)
++ */
++ sp = ((u_int)(stack_base + stack_size) & ~(8-1)) -
++ sizeof(struct target_trapframe);
++
++ /* sp = stack base */
++ regs->regs[13] = sp;
++ /* pc = start function entry */
++ regs->regs[15] = entry & 0xfffffffe;
++ /* r0 = arg */
++ regs->regs[0] = arg;
++ regs->spsr = ARM_CPU_MODE_USR;
++}
++
++static inline void target_thread_init(struct target_pt_regs *regs,
++ struct image_info *infop)
++{
++ abi_long stack = infop->start_stack;
++ memset(regs, 0, sizeof(*regs));
++ regs->ARM_cpsr = 0x10;
++ if (infop->entry & 1)
++ regs->ARM_cpsr |= CPSR_T;
++ regs->ARM_pc = infop->entry & 0xfffffffe;
++ regs->ARM_sp = infop->start_stack;
++ if (bsd_type == target_freebsd) {
++ regs->ARM_lr = infop->entry & 0xfffffffe;
++ }
++ /* FIXME - what to for failure of get_user()? */
++ get_user_ual(regs->ARM_r2, stack + 8); /* envp */
++ get_user_ual(regs->ARM_r1, stack + 4); /* envp */
++ /* XXX: it seems that r0 is zeroed after ! */
++ regs->ARM_r0 = 0;
++ /* For uClinux PIC binaries. */
++ /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
++ regs->ARM_r10 = infop->start_data;
++}
++
++#endif /* !_TARGET_ARCH_THREAD_H_ */
+diff --git a/bsd-user/arm/target_arch_vmparam.h b/bsd-user/arm/target_arch_vmparam.h
+new file mode 100644
+index 0000000..014fc66
+--- /dev/null
++++ b/bsd-user/arm/target_arch_vmparam.h
+@@ -0,0 +1,48 @@
++/*
++ * arm VM parameters definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_VMPARAM_H_
++#define _TARGET_ARCH_VMPARAM_H_
++
++#include "cpu.h"
++
++/* compare to sys/arm/include/vmparam.h */
++#define TARGET_MAXTSIZ (64UL*1024*1024) /* max text size */
++#define TARGET_DFLDSIZ (128UL*1024*1024) /* initial data size limit */
++#define TARGET_MAXDSIZ (512UL*1024*1024) /* max data size */
++#define TARGET_DFLSSIZ (2UL*1024*1024) /* initial stack size limit */
++#define TARGET_MAXSSIZ (8UL*1024*1024) /* max stack size */
++#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */
++
++#define TARGET_RESERVED_VA 0xf7000000
++
++ /* KERNBASE - 512 MB */
++#define TARGET_VM_MAXUSER_ADDRESS (0xc0000000 - (512 * 1024 * 1024))
++#define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS
++
++static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
++{
++ return state->regs[13]; /* sp */
++}
++
++static inline void set_second_rval(CPUARMState *state, abi_ulong retval2)
++{
++ state->regs[1] = retval2;
++}
++
++#endif /* ! _TARGET_ARCH_VMPARAM_H_ */
+diff --git a/bsd-user/bsd-file.h b/bsd-user/bsd-file.h
+new file mode 100644
+index 0000000..fc279a8
+--- /dev/null
++++ b/bsd-user/bsd-file.h
+@@ -0,0 +1,1111 @@
++/*
++ * file related system call shims and definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __BSD_FILE_H_
++#define __BSD_FILE_H_
++
++#include <sys/types.h>
++#include <sys/mount.h>
++#include <sys/uio.h>
++#include <fcntl.h>
++#include <poll.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++#define target_to_host_bitmask(x, tbl) (x)
++
++#define LOCK_PATH(p, arg) do { \
++ (p) = lock_user_string(arg); \
++ if ((p) == NULL) { \
++ return -TARGET_EFAULT; \
++ } \
++} while (0)
++
++#define UNLOCK_PATH(p, arg) unlock_user((p), (arg), 0)
++
++struct target_pollfd {
++ int32_t fd; /* file descriptor */
++ int16_t events; /* requested events */
++ int16_t revents; /* returned events */
++};
++
++static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
++ int count, int copy);
++static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
++ int count, int copy);
++extern int __getcwd(char *path, size_t len);
++
++/* read(2) */
++static inline abi_long do_bsd_read(abi_long arg1, abi_long arg2, abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++
++ p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(read(arg1, p, arg3));
++ unlock_user(p, arg2, ret);
++
++ return ret;
++}
++
++/* pread(2) */
++static inline abi_long do_bsd_pread(void *cpu_env, abi_long arg1,
++ abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
++{
++ abi_long ret;
++ void *p;
++
++ p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ if (regpairs_aligned(cpu_env) != 0) {
++ arg4 = arg5;
++ arg5 = arg6;
++ }
++ ret = get_errno(pread(arg1, p, arg3, target_offset64(arg4, arg5)));
++ unlock_user(p, arg2, ret);
++
++ return ret;
++}
++
++/* readv(2) */
++static inline abi_long do_bsd_readv(abi_long arg1, abi_long arg2, abi_long arg3)
++{
++ abi_long ret;
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (vec == NULL) {
++ return -TARGET_ENOMEM;
++ }
++ if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(readv(arg1, vec, count));
++ unlock_iovec(vec, arg2, count, 1);
++
++ return ret;
++}
++
++/* write(2) */
++static inline abi_long do_bsd_write(abi_long arg1, abi_long arg2, abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++
++ p = lock_user(VERIFY_READ, arg2, arg3, 1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(write(arg1, p, arg3));
++ unlock_user(p, arg2, 0);
++
++ return ret;
++}
++
++/* pwrite(2) */
++static inline abi_long do_bsd_pwrite(void *cpu_env, abi_long arg1,
++ abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
++{
++ abi_long ret;
++ void *p;
++
++ p = lock_user(VERIFY_READ, arg2, arg3, 1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ if (regpairs_aligned(cpu_env) != 0) {
++ arg4 = arg5;
++ arg5 = arg6;
++ }
++ ret = get_errno(pwrite(arg1, p, arg3, target_offset64(arg4, arg5)));
++ unlock_user(p, arg2, 0);
++
++ return ret;
++}
++
++/* writev(2) */
++static inline abi_long do_bsd_writev(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++ abi_long ret;
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (vec == NULL) {
++ return -TARGET_ENOMEM;
++ }
++ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(writev(arg1, vec, count));
++ unlock_iovec(vec, arg2, count, 0);
++
++ return ret;
++}
++
++/* pwritev(2) */
++static inline abi_long do_bsd_pwritev(void *cpu_env, abi_long arg1,
++ abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
++{
++ abi_long ret;
++ int count = arg3;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (vec == NULL) {
++ return -TARGET_ENOMEM;
++ }
++ if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0) {
++ return -TARGET_EFAULT;
++ }
++ if (regpairs_aligned(cpu_env) != 0) {
++ arg4 = arg5;
++ arg5 = arg6;
++ }
++ ret = get_errno(pwritev(arg1, vec, count, target_offset64(arg4, arg5)));
++ unlock_iovec(vec, arg2, count, 0);
++
++ return ret;
++}
++
++/* open(2) */
++static inline abi_long do_bsd_open(abi_long arg1, abi_long arg2, abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(open(path(p), target_to_host_bitmask(arg2, fcntl_flags_tbl),
++ arg3));
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* openat(2) */
++static inline abi_long do_bsd_openat(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg2);
++ ret = get_errno(openat(arg1, path(p),
++ target_to_host_bitmask(arg3, fcntl_flags_tbl), arg4));
++ UNLOCK_PATH(p, arg2);
++
++ return ret;
++}
++
++/* close(2) */
++static inline abi_long do_bsd_close(abi_long arg1)
++{
++
++ return get_errno(close(arg1));
++}
++
++/* closefrom(2) */
++static inline abi_long do_bsd_closefrom(abi_long arg1)
++{
++
++ closefrom(arg1); /* returns void */
++ return get_errno(0);
++}
++
++/* revoke(2) */
++static inline abi_long do_bsd_revoke(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(revoke(p)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* creat(2) (obsolete) */
++static inline abi_long do_bsd_creat(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(open(path(p), O_CREAT | O_TRUNC | O_WRONLY, arg2));
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++
++/* access(2) */
++static inline abi_long do_bsd_access(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(access(path(p), arg2));
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* eaccess(2) */
++static inline abi_long do_bsd_eaccess(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(eaccess(path(p), arg2));
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* faccessat(2) */
++static inline abi_long do_bsd_faccessat(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg2);
++ ret = get_errno(faccessat(arg1, p, arg3, arg4)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg2);
++
++ return ret;
++}
++
++/* chdir(2) */
++static inline abi_long do_bsd_chdir(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(chdir(p)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* fchdir(2) */
++static inline abi_long do_bsd_fchdir(abi_long arg1)
++{
++
++ return get_errno(fchdir(arg1));
++}
++
++/* rename(2) */
++static inline abi_long do_bsd_rename(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p1, *p2;
++
++ LOCK_PATH(p1, arg1);
++ LOCK_PATH(p2, arg2);
++ if (!p1 || !p2) {
++ ret = -TARGET_EFAULT;
++ } else {
++ ret = get_errno(rename(p1, p2)); /* XXX path(p1), path(p2) */
++ }
++ UNLOCK_PATH(p2, arg2);
++ UNLOCK_PATH(p1, arg1);
++
++ return ret;
++}
++
++/* renameat(2) */
++static inline abi_long do_bsd_renameat(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++ abi_long ret;
++ void *p1, *p2;
++
++ LOCK_PATH(p1, arg1);
++ LOCK_PATH(p2, arg2);
++ if (!p1 || !p2) {
++ ret = -TARGET_EFAULT;
++ } else {
++ ret = get_errno(renameat(arg1, p1, arg3, p2));
++ }
++ UNLOCK_PATH(p2, arg2);
++ UNLOCK_PATH(p1, arg1);
++
++ return ret;
++}
++
++/* link(2) */
++static inline abi_long do_bsd_link(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p1, *p2;
++
++ LOCK_PATH(p1, arg1);
++ LOCK_PATH(p2, arg2);
++ if (!p1 || !p2) {
++ ret = -TARGET_EFAULT;
++ } else {
++ ret = get_errno(link(p1, p2)); /* XXX path(p1), path(p2) */
++ }
++ UNLOCK_PATH(p2, arg2);
++ UNLOCK_PATH(p1, arg1);
++
++ return ret;
++}
++
++/* linkat(2) */
++static inline abi_long do_bsd_linkat(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5)
++{
++ abi_long ret;
++ void *p1, *p2;
++
++ LOCK_PATH(p1, arg2);
++ LOCK_PATH(p2, arg4);
++ if (!p1 || !p2) {
++ ret = -TARGET_EFAULT;
++ } else {
++ ret = get_errno(linkat(arg1, p1, arg3, p2, arg5));
++ }
++ UNLOCK_PATH(p2, arg4);
++ UNLOCK_PATH(p1, arg2);
++
++ return ret;
++}
++
++/* unlink(2) */
++static inline abi_long do_bsd_unlink(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(unlink(p)); /* XXX path(p) */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* unlinkat(2) */
++static inline abi_long do_bsd_unlinkat(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg2);
++ ret = get_errno(unlinkat(arg1, p, arg3)); /* XXX path(p) */
++ UNLOCK_PATH(p, arg2);
++
++ return ret;
++}
++
++/* mkdir(2) */
++static inline abi_long do_bsd_mkdir(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(mkdir(p, arg2)); /* XXX path(p) */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++
++/* mkdirat(2) */
++static inline abi_long do_bsd_mkdirat(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg2);
++ ret = get_errno(mkdirat(arg1, p, arg3));
++ UNLOCK_PATH(p, arg2);
++
++ return ret;
++}
++
++
++/* rmdir(2) */
++static inline abi_long do_bsd_rmdir(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(rmdir(p)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* undocumented __getcwd(char *buf, size_t len) system call */
++static inline abi_long do_bsd___getcwd(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(__getcwd(p, arg2));
++ unlock_user(p, arg1, ret);
++
++ return ret;
++}
++
++/* dup(2) */
++static inline abi_long do_bsd_dup(abi_long arg1)
++{
++
++ return get_errno(dup(arg1));
++}
++
++/* dup2(2) */
++static inline abi_long do_bsd_dup2(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(dup2(arg1, arg2));
++}
++
++/* truncate(2) */
++static inline abi_long do_bsd_truncate(void *cpu_env, abi_long arg1,
++ abi_long arg2, abi_long arg3, abi_long arg4)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ if (regpairs_aligned(cpu_env) != 0) {
++ arg2 = arg3;
++ arg3 = arg4;
++ }
++ ret = get_errno(truncate(p, target_offset64(arg2, arg3)));
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* ftruncate(2) */
++static inline abi_long do_bsd_ftruncate(void *cpu_env, abi_long arg1,
++ abi_long arg2, abi_long arg3, abi_long arg4)
++{
++
++ if (regpairs_aligned(cpu_env) != 0) {
++ arg2 = arg3;
++ arg3 = arg4;
++ }
++ return get_errno(ftruncate(arg1, target_offset64(arg2, arg3)));
++}
++
++/* acct(2) */
++static inline abi_long do_bsd_acct(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++
++ if (arg1 == 0) {
++ ret = get_errno(acct(NULL));
++ } else {
++ LOCK_PATH(p, arg1);
++ ret = get_errno(acct(path(p)));
++ UNLOCK_PATH(p, arg1);
++ }
++ return ret;
++}
++
++/* sync(2) */
++static inline abi_long do_bsd_sync(void)
++{
++
++ sync();
++ return 0;
++}
++
++/* mount(2) */
++static inline abi_long do_bsd_mount(abi_long arg1, abi_long arg2, abi_long arg3,
++ abi_long arg4)
++{
++ abi_long ret;
++ void *p1, *p2;
++
++ LOCK_PATH(p1, arg1);
++ LOCK_PATH(p2, arg2);
++ if (!p1 || !p2) {
++ ret = -TARGET_EFAULT;
++ } else {
++ /*
++ * XXX arg4 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 (arg4 == 0) {
++ ret = get_errno(mount(p1, p2, arg3, NULL)); /* XXX path(p2)? */
++ } else {
++ ret = get_errno(mount(p1, p2, arg3, g2h(arg4))); /* XXX path(p2)? */
++ }
++ }
++ UNLOCK_PATH(p2, arg2);
++ UNLOCK_PATH(p1, arg1);
++
++ return ret;
++}
++
++/* unmount(2) */
++static inline abi_long do_bsd_unmount(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(unmount(p, arg2)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* nmount(2) */
++static inline abi_long do_bsd_nmount(abi_long arg1, abi_long count,
++ abi_long flags)
++{
++ abi_long ret;
++ struct iovec *vec;
++
++ vec = alloca(count * sizeof(struct iovec));
++ if (lock_iovec(VERIFY_READ, vec, arg1, count, 1) < 0) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(nmount(vec, count, flags));
++ unlock_iovec(vec, arg1, count, 0);
++
++ return ret;
++}
++
++/* symlink(2) */
++static inline abi_long do_bsd_symlink(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p1, *p2;
++
++ LOCK_PATH(p1, arg1);
++ LOCK_PATH(p2, arg2);
++ if (!p1 || !p2) {
++ ret = -TARGET_EFAULT;
++ } else {
++ ret = get_errno(symlink(p1, p2)); /* XXX path(p1), path(p2) */
++ }
++ UNLOCK_PATH(p2, arg2);
++ UNLOCK_PATH(p1, arg1);
++
++ return ret;
++}
++
++/* symlinkat(2) */
++static inline abi_long do_bsd_symlinkat(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++ abi_long ret;
++ void *p1, *p2;
++
++ LOCK_PATH(p1, arg1);
++ LOCK_PATH(p2, arg3);
++ if (!p1 || !p2) {
++ ret = -TARGET_EFAULT;
++ } else {
++ ret = get_errno(symlinkat(p1, arg2, p2)); /* XXX path(p1), path(p2) */
++ }
++ UNLOCK_PATH(p2, arg3);
++ UNLOCK_PATH(p1, arg1);
++
++ return ret;
++}
++
++/* readlink(2) */
++static inline abi_long do_bsd_readlink(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++ abi_long ret;
++ void *p1, *p2;
++
++ LOCK_PATH(p1, arg1);
++ p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
++ if (!p1 || !p2) {
++ ret = -TARGET_EFAULT;
++ } else {
++ ret = get_errno(readlink(path(p1), p2, arg3));
++ }
++ unlock_user(p2, arg2, ret);
++ UNLOCK_PATH(p1, arg1);
++
++ return ret;
++}
++
++/* readlinkat(2) */
++static inline abi_long do_bsd_readlinkat(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++ abi_long ret;
++ void *p1, *p2;
++
++ LOCK_PATH(p1, arg2);
++ p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
++ if (!p1 || !p2) {
++ ret = -TARGET_EFAULT;
++ } else {
++ ret = get_errno(readlinkat(arg1, p1, p2, arg4));
++ }
++ unlock_user(p2, arg3, ret);
++ UNLOCK_PATH(p1, arg2);
++
++ return ret;
++}
++
++/* chmod(2) */
++static inline abi_long do_bsd_chmod(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(chmod(p, arg2)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* fchmod(2) */
++static inline abi_long do_bsd_fchmod(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(fchmod(arg1, arg2));
++}
++
++/* lchmod(2) */
++static inline abi_long do_bsd_lchmod(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(lchmod(p, arg2)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* fchmodat(2) */
++static inline abi_long do_bsd_fchmodat(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg2);
++ ret = get_errno(fchmodat(arg1, p, arg3, arg4));
++ UNLOCK_PATH(p, arg2);
++
++ return ret;
++}
++
++/* mknod(2) */
++static inline abi_long do_bsd_mknod(abi_long arg1, abi_long arg2, abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(mknod(p, arg2, arg3)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* mknodat(2) */
++static inline abi_long do_bsd_mknodat(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg2);
++ ret = get_errno(mknodat(arg1, p, arg3, arg4));
++ UNLOCK_PATH(p, arg2);
++
++ return ret;
++}
++
++/* chown(2) */
++static inline abi_long do_bsd_chown(abi_long arg1, abi_long arg2, abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(chown(p, arg2, arg3)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* fchown(2) */
++static inline abi_long do_bsd_fchown(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ return get_errno(fchown(arg1, arg2, arg3));
++}
++
++/* lchown(2) */
++static inline abi_long do_bsd_lchown(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(lchown(p, arg2, arg3)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* fchownat(2) */
++static inline abi_long do_bsd_fchownat(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg2);
++ ret = get_errno(fchownat(arg1, p, arg3, arg4, arg5)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg2);
++
++ return ret;
++}
++
++/* chflags(2) */
++static inline abi_long do_bsd_chflags(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(chflags(p, arg2)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* lchflags(2) */
++static inline abi_long do_bsd_lchflags(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(lchflags(p, arg2)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* fchflags(2) */
++static inline abi_long do_bsd_fchflags(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(fchflags(arg1, arg2));
++}
++
++/* chroot(2) */
++static inline abi_long do_bsd_chroot(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(chroot(p)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* flock(2) */
++static abi_long do_bsd_flock(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(flock(arg1, arg2));
++}
++
++/* mkfifo(2) */
++static inline abi_long do_bsd_mkfifo(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(mkfifo(p, arg2)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* mkfifoat(2) */
++static inline abi_long do_bsd_mkfifoat(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg2);
++ ret = get_errno(mkfifoat(arg1, p, arg3));
++ UNLOCK_PATH(p, arg2);
++
++ return ret;
++}
++
++/* pathconf(2) */
++static inline abi_long do_bsd_pathconf(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(pathconf(p, arg2)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* lpathconf(2) */
++static inline abi_long do_bsd_lpathconf(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(lpathconf(p, arg2)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* fpathconf(2) */
++static inline abi_long do_bsd_fpathconf(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(fpathconf(arg1, arg2));
++}
++
++/* undelete(2) */
++static inline abi_long do_bsd_undelete(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(undelete(p)); /* XXX path(p)? */
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* poll(2) */
++static abi_long do_bsd_poll(abi_long arg1, abi_long arg2, abi_long arg3)
++{
++ abi_long ret;
++ nfds_t i, nfds = arg2;
++ int timeout = arg3;
++ struct pollfd *pfd;
++ struct target_pollfd *target_pfd;
++
++ target_pfd = lock_user(VERIFY_WRITE, arg1,
++ sizeof(struct target_pollfd) * nfds, 1);
++ if (!target_pfd) {
++ return -TARGET_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);
++
++ return ret;
++}
++
++/*
++ * undocumented openbsd_poll(struct pollfd *fds, u_int nfds, int
++ * timeout) system call.
++ */
++static abi_long do_bsd_openbsd_poll(abi_long arg1, abi_long arg2, abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall openbsd_poll()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* lseek(2) */
++static abi_long do_bsd_lseek(void *cpu_env, abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5)
++{
++ abi_long ret;
++#if TARGET_ABI_BITS == 32
++ int64_t res;
++
++ /* 32-bit arch's use two 32 registers for 64 bit return value */
++ if (regpairs_aligned(cpu_env) != 0) {
++ res = lseek(arg1, target_offset64(arg3, arg4), arg5);
++ } else {
++ res = lseek(arg1, target_offset64(arg2, arg3), arg4);
++ }
++ if (res == -1) {
++ ret = get_errno(res);
++ } else {
++ ret = res & 0xFFFFFFFF;
++ set_second_rval(cpu_env, (res >> 32) & 0xFFFFFFFF);
++ }
++#else
++ ret = get_errno(lseek(arg1, arg2, arg3));
++#endif
++ return ret;
++}
++
++/* pipe(2) */
++static abi_long do_bsd_pipe(void *cpu_env, abi_long arg1)
++{
++ abi_long ret;
++ int host_pipe[2];
++ int host_ret = pipe(host_pipe);
++
++ if (host_ret != -1) {
++ set_second_rval(cpu_env, host_pipe[1]);
++ ret = host_pipe[0];
++ } else {
++ ret = get_errno(host_ret);
++ }
++ return ret;
++}
++
++/* swapon(2) */
++static abi_long do_bsd_swapon(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(swapon(path(p)));
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/* swapoff(2) */
++static abi_long do_bsd_swapoff(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(swapoff(path(p)));
++ UNLOCK_PATH(p, arg1);
++
++ return ret;
++}
++
++/*
++ * undocumented freebsd6_pread(int fd, void *buf, size_t nbyte, int pad,
++ * off_t offset) system call.
++ */
++static abi_long do_bsd_freebsd6_pread(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall freebsd6_pread()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * undocumented freebsd6_pwrite(int fd, void *buf, size_t nbyte, int pad,
++ * off_t offset) system call.
++ */
++static abi_long do_bsd_freebsd6_pwrite(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall freebsd6_pwrite()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * undocumented freebsd6_lseek(int fd, int pad, off_t offset, int whence)
++ * system call.
++ */
++static abi_long do_bsd_freebsd6_lseek(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall freebsd6_lseek()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * undocumented freebsd6_truncate(char *path, int pad, off_t offset) system
++ * call.
++ */
++static abi_long do_bsd_freebsd6_truncate(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall freebsd6_truncate()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * undocumented freebsd6_ftruncate(int fd, int pad, off_t offset) system
++ * call.
++ */
++static abi_long do_bsd_freebsd6_ftruncate(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall freebsd6_ftruncate()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* !__BSD_FILE_H_ */
+diff --git a/bsd-user/bsd-ioctl.c b/bsd-user/bsd-ioctl.c
+new file mode 100644
+index 0000000..95505a4
+--- /dev/null
++++ b/bsd-user/bsd-ioctl.c
+@@ -0,0 +1,448 @@
++/*
++ * BSD ioctl(2) emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <sys/param.h>
++#include <sys/ioctl.h>
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
++#include <sys/_termios.h>
++#else
++#include <sys/termios.h>
++#endif
++#include <sys/ttycom.h>
++#include <sys/filio.h>
++
++#include "qemu.h"
++#include "qemu-common.h"
++
++#include "bsd-ioctl.h"
++#include "os-ioctl-filio.h"
++#include "os-ioctl-ttycom.h"
++
++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) },
++};
++
++
++/* ioctl structure type definitions */
++#define STRUCT(name, ...) STRUCT_ ## name,
++#define STRUCT_SPECIAL(name) STRUCT_ ## name,
++enum {
++#include "os-ioctl-types.h"
++};
++#undef STRUCT
++#undef STRUCT_SPECIAL
++
++#define STRUCT(name, ...) \
++ static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
++#define STRUCT_SPECIAL(name)
++#include "os-ioctl-types.h"
++#undef STRUCT
++#undef STRUCT_SPECIAL
++
++
++struct IOCTLEntry;
++
++typedef abi_long do_ioctl_fn(const struct 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];
++};
++typedef struct IOCTLEntry IOCTLEntry;
++
++#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__ } },
++#include "os-ioctl-cmds.h"
++ { 0, 0 },
++};
++
++abi_long do_bsd_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 (ie->target_cmd == 0) {
++ 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));
++ break;
++
++ case IOC_RW:
++ /* fallthrough */
++ 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;
++}
++
++void init_bsd_ioctl(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);
++#include "os-ioctl-types.h"
++#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/bsd-ioctl.h b/bsd-user/bsd-ioctl.h
+new file mode 100644
+index 0000000..b593c88
+--- /dev/null
++++ b/bsd-user/bsd-ioctl.h
+@@ -0,0 +1,27 @@
++/*
++ * ioctl system call definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __BSD_IOCTL_H_
++#define __BSD_IOCTL_H_
++
++abi_long do_bsd_ioctl(int fd, abi_long cmd, abi_long arg);
++void init_bsd_ioctl(void);
++
++#endif /* !__BSD_IOCTL_H_ */
++
+diff --git a/bsd-user/bsd-mem.c b/bsd-user/bsd-mem.c
+new file mode 100644
+index 0000000..bfe03aa
+--- /dev/null
++++ b/bsd-user/bsd-mem.c
+@@ -0,0 +1,122 @@
++/*
++ * memory management system conversion routines
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/ipc.h>
++#include <sys/shm.h>
++
++#include "qemu.h"
++#include "qemu-bsd.h"
++
++struct bsd_shm_regions bsd_shm_regions[N_BSD_SHM_REGIONS];
++
++abi_ulong bsd_target_brk;
++abi_ulong bsd_target_original_brk;
++
++void target_set_brk(abi_ulong new_brk)
++{
++
++ bsd_target_original_brk = bsd_target_brk = HOST_PAGE_ALIGN(new_brk);
++}
++
++abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
++ abi_ulong target_addr)
++{
++ struct target_ipc_perm *target_ip;
++
++ if (!lock_user_struct(VERIFY_READ, target_ip, target_addr, 1)) {
++ return -TARGET_EFAULT;
++ }
++ __get_user(host_ip->cuid, &target_ip->cuid);
++ __get_user(host_ip->cgid, &target_ip->cgid);
++ __get_user(host_ip->uid, &target_ip->uid);
++ __get_user(host_ip->gid, &target_ip->gid);
++ __get_user(host_ip->mode, &target_ip->mode);
++ __get_user(host_ip->seq, &target_ip->seq);
++ __get_user(host_ip->key, &target_ip->key);
++ unlock_user_struct(target_ip, target_addr, 0);
++
++ return 0;
++}
++
++abi_long host_to_target_ipc_perm(abi_ulong target_addr,
++ struct ipc_perm *host_ip)
++{
++ struct target_ipc_perm *target_ip;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_ip, target_addr, 0)) {
++ return -TARGET_EFAULT;
++ }
++ __put_user(host_ip->cuid, &target_ip->cuid);
++ __put_user(host_ip->cgid, &target_ip->cgid);
++ __put_user(host_ip->uid, &target_ip->uid);
++ __put_user(host_ip->gid, &target_ip->gid);
++ __put_user(host_ip->mode, &target_ip->mode);
++ __put_user(host_ip->seq, &target_ip->seq);
++ __put_user(host_ip->key, &target_ip->key);
++ unlock_user_struct(target_ip, target_addr, 1);
++
++ return 0;
++}
++
++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;
++}
++
++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;
++}
++
+diff --git a/bsd-user/bsd-mem.h b/bsd-user/bsd-mem.h
+new file mode 100644
+index 0000000..88c01ec
+--- /dev/null
++++ b/bsd-user/bsd-mem.h
+@@ -0,0 +1,393 @@
++/*
++ * memory management system call shims and definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++/*--
++ * Copyright (c) 1982, 1986, 1993
++ * The Regents of the University of California. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ * 4. Neither the name of the University nor the names of its contributors
++ * may be used to endorse or promote products derived from this software
++ * without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
++ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
++ * SUCH DAMAGE.
++ */
++
++#ifndef _BSD_MMAN_H_
++#define _BSD_MMAN_H_
++
++#include <sys/types.h>
++#include <sys/ipc.h>
++#include <sys/mman.h>
++#include <sys/shm.h>
++#include <fcntl.h>
++
++#include "qemu-bsd.h"
++
++extern struct bsd_shm_regions bsd_shm_regions[];
++extern abi_ulong bsd_target_brk;
++extern abi_ulong bsd_target_original_brk;
++
++/* mmap(2) */
++static inline abi_long do_bsd_mmap(void *cpu_env, abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6, abi_long arg7,
++ abi_long arg8)
++{
++
++ if (regpairs_aligned(cpu_env) != 0) {
++ arg6 = arg7;
++ arg7 = arg8;
++ }
++ return get_errno(target_mmap(arg1, arg2, arg3,
++ target_to_host_bitmask(arg4, mmap_flags_tbl), arg5,
++ target_offset64(arg6, arg7)));
++}
++
++/* munmap(2) */
++static inline abi_long do_bsd_munmap(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(target_munmap(arg1, arg2));
++}
++
++/* mprotect(2) */
++static inline abi_long do_bsd_mprotect(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ return get_errno(target_mprotect(arg1, arg2, arg3));
++}
++
++/* msync(2) */
++static inline abi_long do_bsd_msync(abi_long arg1, abi_long arg2, abi_long arg3)
++{
++
++ return get_errno(msync(g2h(arg1), arg2, arg3));
++}
++
++/* mlock(2) */
++static inline abi_long do_bsd_mlock(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(mlock(g2h(arg1), arg2));
++}
++
++/* munlock(2) */
++static inline abi_long do_bsd_munlock(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(munlock(g2h(arg1), arg2));
++}
++
++/* mlockall(2) */
++static inline abi_long do_bsd_mlockall(abi_long arg1)
++{
++
++ return get_errno(mlockall(arg1));
++}
++
++/* munlockall(2) */
++static inline abi_long do_bsd_munlockall(void)
++{
++
++ return get_errno(munlockall());
++}
++
++/* madvise(2) */
++static inline abi_long do_bsd_madvise(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++ /*
++ * 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.
++ */
++ return get_errno(0);
++}
++
++/* minherit(2) */
++static inline abi_long do_bsd_minherit(abi_long addr, abi_long len,
++ abi_long inherit)
++{
++
++ return get_errno(minherit(g2h(addr), len, inherit));
++}
++
++/* mincore(2) */
++static inline abi_long do_bsd_mincore(abi_ulong target_addr, abi_ulong len,
++ abi_ulong target_vec)
++{
++ abi_long ret;
++ void *p, *a;
++
++ a = lock_user(VERIFY_WRITE, target_addr, len, 0);
++ if (a == NULL) {
++ return -TARGET_EFAULT;
++ }
++ p = lock_user_string(target_vec);
++ if (p == NULL) {
++ unlock_user(a, target_addr, 0);
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(mincore(a, len, p));
++ unlock_user(p, target_vec, ret);
++ unlock_user(a, target_addr, 0);
++
++ return ret;
++}
++
++/* break() XXX this needs some more work. */
++static inline abi_long do_obreak(abi_ulong new_brk)
++{
++ abi_ulong brk_page;
++ abi_long mapped_addr;
++ int new_alloc_size;
++
++ return -TARGET_EINVAL;
++
++ if (!new_brk) {
++ return 0;
++ }
++ if (new_brk < bsd_target_original_brk) {
++ return -TARGET_EINVAL;
++ }
++
++ brk_page = HOST_PAGE_ALIGN(bsd_target_brk);
++
++ /* If the new brk is less than this, set it and we're done... */
++ if (new_brk < brk_page) {
++ bsd_target_brk = new_brk;
++ return 0;
++ }
++
++ /* We need to allocate more memory after the brk... */
++ new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
++ mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
++ PROT_READ|PROT_WRITE, MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0));
++
++ if (!is_error(mapped_addr)) {
++ bsd_target_brk = new_brk;
++ } else {
++ return mapped_addr;
++ }
++
++ return 0;
++}
++
++/* shm_open(2) */
++static inline abi_long do_bsd_shm_open(abi_ulong arg1, abi_long arg2,
++ abi_long arg3)
++{
++ int ret;
++ void *p;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(shm_open(path(p),
++ target_to_host_bitmask(arg2, fcntl_flags_tbl), arg3));
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* shm_unlink(2) */
++static inline abi_long do_bsd_shm_unlink(abi_ulong arg1)
++{
++ int ret;
++ void *p;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(shm_unlink(p)); /* XXX path(p)? */
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* shmget(2) */
++static inline abi_long do_bsd_shmget(abi_long arg1, abi_ulong arg2,
++ abi_long arg3)
++{
++
++ return get_errno(shmget(arg1, arg2, arg3));
++}
++
++/* shmctl(2) */
++static inline abi_long do_bsd_shmctl(abi_long shmid, abi_long cmd,
++ abi_ulong 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;
++}
++
++/* shmat(2) */
++static inline abi_long do_bsd_shmat(int shmid, abi_ulong shmaddr, int shmflg)
++{
++ abi_ulong raddr;
++ abi_long ret;
++ void *host_raddr;
++ struct shmid_ds shm_info;
++ int i;
++
++ /* 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_BSD_SHM_REGIONS; i++) {
++ if (bsd_shm_regions[i].start == 0) {
++ bsd_shm_regions[i].start = raddr;
++ bsd_shm_regions[i].size = shm_info.shm_segsz;
++ break;
++ }
++ }
++
++ mmap_unlock();
++ return raddr;
++}
++
++/* shmdt(2) */
++static inline abi_long do_bsd_shmdt(abi_ulong shmaddr)
++{
++ int i;
++
++ for (i = 0; i < N_BSD_SHM_REGIONS; ++i) {
++ if (bsd_shm_regions[i].start == shmaddr) {
++ bsd_shm_regions[i].start = 0;
++ page_set_flags(shmaddr,
++ shmaddr + bsd_shm_regions[i].size, 0);
++ break;
++ }
++ }
++
++ return get_errno(shmdt(g2h(shmaddr)));
++}
++
++
++static inline abi_long do_bsd_vadvise(void)
++{
++ /* See sys_ovadvise() in vm_unix.c */
++ qemu_log("qemu: Unsupported syscall vadvise()\n");
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_bsd_sbrk(void)
++{
++ /* see sys_sbrk() in vm_mmap.c */
++ qemu_log("qemu: Unsupported syscall sbrk()\n");
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_bsd_sstk(void)
++{
++ /* see sys_sstk() in vm_mmap.c */
++ qemu_log("qemu: Unsupported syscall sstk()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * undocumented freebsd6_mmap(caddr_t addr, size_t len, int prot, int
++ * flags, int fd, int pad, off_t pos) system call.
++ */
++static inline abi_long do_bsd_freebsd6_mmap(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6,
++ abi_long arg7)
++{
++
++ qemu_log("qemu: Unsupported syscall freebsd6_mmap()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* !_BSD_MMAN_H_ */
+diff --git a/bsd-user/bsd-misc.c b/bsd-user/bsd-misc.c
+new file mode 100644
+index 0000000..bc85473
+--- /dev/null
++++ b/bsd-user/bsd-misc.c
+@@ -0,0 +1,209 @@
++/*
++ * BSD misc system call conversions routines
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <sys/ipc.h>
++#include <sys/msg.h>
++#include <sys/sem.h>
++#include <sys/uuid.h>
++
++#include "qemu.h"
++#include "qemu-bsd.h"
++
++/*
++ * BSD uuidgen(2) struct uuid conversion
++ */
++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;
++}
++
++abi_long target_to_host_semarray(int semid, unsigned short **host_array,
++ abi_ulong target_addr)
++{
++ abi_long ret;
++ int nsems, i;
++ unsigned short *array;
++ union semun semun;
++ struct semid_ds semid_ds;
++
++ 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 = (unsigned short *)malloc(nsems * sizeof(unsigned short));
++ array = lock_user(VERIFY_READ, target_addr,
++ nsems*sizeof(unsigned short), 1);
++ if (array == NULL) {
++ free(*host_array);
++ return -TARGET_EFAULT;
++ }
++ for (i = 0; i < nsems; i++) {
++ (*host_array)[i] = array[i];
++ }
++ unlock_user(array, target_addr, 0);
++
++ return 0;
++}
++
++abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
++ unsigned short **host_array)
++{
++ abi_long ret;
++ int nsems, i;
++ unsigned short *array;
++ union semun semun;
++ struct semid_ds semid_ds;
++
++ semun.buf = &semid_ds;
++
++ ret = semctl(semid, 0, IPC_STAT, semun);
++ if (ret == -1) {
++ free(*host_array);
++ return get_errno(ret);
++ }
++
++ nsems = semid_ds.sem_nsems;
++ array = (unsigned short *)lock_user(VERIFY_WRITE, target_addr,
++ nsems*sizeof(unsigned short), 0);
++ if (array == NULL) {
++ free(*host_array);
++ return -TARGET_EFAULT;
++ }
++ for (i = 0; i < nsems; i++) {
++ array[i] = (*host_array)[i];
++ }
++ free(*host_array);
++ unlock_user(array, target_addr, 1);
++ return 0;
++}
++
++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 +
++ 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 = 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);
++ return 0;
++}
++
++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 +
++ 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_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);
++
++ return 0;
++}
++
++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;
++}
++
++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;
++}
++
+diff --git a/bsd-user/bsd-misc.h b/bsd-user/bsd-misc.h
+new file mode 100644
+index 0000000..0c34089
+--- /dev/null
++++ b/bsd-user/bsd-misc.h
+@@ -0,0 +1,339 @@
++/*
++ * miscellaneous BSD system call shims
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __BSD_MISC_H_
++#define __BSD_MISC_H_
++
++#include <sys/types.h>
++#include <sys/ipc.h>
++#include <sys/msg.h>
++#include <sys/sem.h>
++#include <sys/uuid.h>
++
++#include "qemu-bsd.h"
++
++/* quotactl(2) */
++static inline abi_long do_bsd_quotactl(abi_ulong path, abi_long cmd,
++ abi_ulong target_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall quotactl()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* reboot(2) */
++static inline abi_long do_bsd_reboot(abi_long how)
++{
++
++ qemu_log("qemu: Unsupported syscall reboot()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* uuidgen(2) */
++static inline abi_long do_bsd_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 (host_uuid == NULL) {
++ return -TARGET_ENOMEM;
++ }
++
++ ret = get_errno(uuidgen(host_uuid, count));
++ if (is_error(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 (is_error(ret)) {
++ goto out;
++ }
++ }
++
++out:
++ g_free(host_uuid);
++ return ret;
++}
++
++
++/*
++ * System V Semaphores
++ */
++
++/* semget(2) */
++static inline abi_long do_bsd_semget(abi_long key, int nsems,
++ int target_flags)
++{
++
++ return get_errno(semget(key, nsems,
++ target_to_host_bitmask(target_flags, ipc_flags_tbl)));
++}
++
++/* semop(2) */
++static inline abi_long do_bsd_semop(int semid, abi_long ptr, unsigned nsops)
++{
++ struct sembuf sops[nsops];
++ struct target_sembuf *target_sembuf;
++ int i;
++
++ target_sembuf = lock_user(VERIFY_READ, ptr,
++ nsops * sizeof(struct target_sembuf), 1);
++ if (target_sembuf == NULL) {
++ return -TARGET_EFAULT;
++ }
++ for (i = 0; i < nsops; i++) {
++ __get_user(sops[i].sem_num, &target_sembuf[i].sem_num);
++ __get_user(sops[i].sem_op, &target_sembuf[i].sem_op);
++ __get_user(sops[i].sem_flg, &target_sembuf[i].sem_flg);
++ }
++ unlock_user(target_sembuf, ptr, 0);
++
++ return semop(semid, sops, nsops);
++}
++
++/* __semctl(2) */
++static inline abi_long do_bsd___semctl(int semid, int semnum, int target_cmd,
++ union target_semun target_su)
++{
++ union semun arg;
++ struct semid_ds dsarg;
++ unsigned short *array = NULL;
++ int host_cmd;
++ abi_long ret = 0;
++ abi_long err;
++ abi_ulong target_addr;
++
++ switch (target_cmd) {
++ case TARGET_GETVAL:
++ host_cmd = GETVAL;
++ break;
++
++ case TARGET_SETVAL:
++ host_cmd = SETVAL;
++ break;
++
++ case TARGET_GETALL:
++ host_cmd = GETALL;
++ break;
++
++ case TARGET_SETALL:
++ host_cmd = SETALL;
++ break;
++
++ case TARGET_IPC_STAT:
++ host_cmd = IPC_STAT;
++ break;
++
++ case TARGET_IPC_SET:
++ host_cmd = IPC_SET;
++ break;
++
++ case TARGET_IPC_RMID:
++ host_cmd = IPC_RMID;
++ break;
++
++ case TARGET_GETPID:
++ host_cmd = GETPID;
++ break;
++
++ case TARGET_GETNCNT:
++ host_cmd = GETNCNT;
++ break;
++
++ case TARGET_GETZCNT:
++ host_cmd = GETZCNT;
++ break;
++
++ default:
++ return -TARGET_EINVAL;
++ }
++
++ switch (host_cmd) {
++ case GETVAL:
++ case SETVAL:
++ arg.val = tswap32(target_su.val);
++ ret = get_errno(semctl(semid, semnum, host_cmd, arg));
++ target_su.val = tswap32(arg.val);
++ break;
++
++ case GETALL:
++ case SETALL:
++ if (get_user_ual(target_addr, (abi_ulong)target_su.array)) {
++ return -TARGET_EFAULT;
++ }
++ err = target_to_host_semarray(semid, &array, target_addr);
++ if (is_error(err)) {
++ return err;
++ }
++ arg.array = array;
++ ret = get_errno(semctl(semid, semnum, host_cmd, arg));
++ err = host_to_target_semarray(semid, target_addr, &array);
++ if (is_error(err)) {
++ return err;
++ }
++ break;
++
++ case IPC_STAT:
++ case IPC_SET:
++ if (get_user_ual(target_addr, (abi_ulong)target_su.buf)) {
++ return -TARGET_EFAULT;
++ }
++ err = target_to_host_semid_ds(&dsarg, target_addr);
++ if (is_error(err)) {
++ return err;
++ }
++ arg.buf = &dsarg;
++ ret = get_errno(semctl(semid, semnum, host_cmd, arg));
++ err = host_to_target_semid_ds(target_addr, &dsarg);
++ if (is_error(err)) {
++ return err;
++ }
++ break;
++
++ case IPC_RMID:
++ case GETPID:
++ case GETNCNT:
++ case GETZCNT:
++ ret = get_errno(semctl(semid, semnum, host_cmd, NULL));
++ break;
++
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++ return ret;
++}
++
++/* msgctl(2) */
++static inline abi_long do_bsd_msgctl(int msgid, int target_cmd, abi_long ptr)
++{
++ struct msqid_ds dsarg;
++ abi_long ret = -TARGET_EINVAL;
++ int host_cmd;
++
++ switch (target_cmd) {
++ case TARGET_IPC_STAT:
++ host_cmd = IPC_STAT;
++ break;
++
++ case TARGET_IPC_SET:
++ host_cmd = IPC_SET;
++ break;
++
++ case TARGET_IPC_RMID:
++ host_cmd = IPC_RMID;
++ break;
++
++ default:
++ return -TARGET_EINVAL;
++ }
++
++ switch (host_cmd) {
++ case IPC_STAT:
++ case IPC_SET:
++ if (target_to_host_msqid_ds(&dsarg, ptr)) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(msgctl(msgid, host_cmd, &dsarg));
++ if (host_to_target_msqid_ds(ptr, &dsarg)) {
++ return -TARGET_EFAULT;
++ }
++ break;
++
++ case IPC_RMID:
++ ret = get_errno(msgctl(msgid, host_cmd, NULL));
++ break;
++
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++ return ret;
++}
++
++/* msgsnd(2) */
++static inline abi_long do_bsd_msgsnd(int msqid, abi_long msgp,
++ unsigned int msgsz, int msgflg)
++{
++ struct target_msgbuf *target_mb;
++ struct mymsg *host_mb;
++ abi_long ret;
++
++ if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) {
++ return -TARGET_EFAULT;
++ }
++ host_mb = g_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));
++ g_free(host_mb);
++ unlock_user_struct(target_mb, msgp, 0);
++
++ return ret;
++}
++
++/* msgrcv(2) */
++static inline abi_long do_bsd_msgrcv(int msqid, abi_long msgp,
++ unsigned int msgsz, abi_long msgtyp, int msgflg)
++{
++ struct target_msgbuf *target_mb = NULL;
++ 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 == NULL) {
++ 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 != NULL) {
++ unlock_user_struct(target_mb, msgp, 1);
++ }
++ g_free(host_mb);
++ return ret;
++}
++
++/* getdtablesize(2) */
++static inline abi_long do_bsd_getdtablesize(void)
++{
++
++ return get_errno(getdtablesize());
++}
++
++#endif /* ! __BSD_MISC_H_ */
+diff --git a/bsd-user/bsd-proc.c b/bsd-user/bsd-proc.c
+new file mode 100644
+index 0000000..a4bcdc8
+--- /dev/null
++++ b/bsd-user/bsd-proc.c
+@@ -0,0 +1,160 @@
++/*
++ * BSD process related system call helpers
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <sys/resource.h>
++#include <sys/wait.h>
++
++#include "qemu.h"
++#include "qemu-bsd.h"
++
++/*
++ * resource/rusage conversion
++ */
++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;
++ }
++}
++
++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;
++}
++
++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;
++}
++
++abi_long host_to_target_rusage(abi_ulong target_addr,
++ const struct rusage *rusage)
++{
++ struct target_freebsd_rusage *target_rusage;
++
++ if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0)) {
++ return -TARGET_EFAULT;
++ }
++ __put_user(rusage->ru_utime.tv_sec, &target_rusage->ru_utime.tv_sec);
++ __put_user(rusage->ru_utime.tv_usec, &target_rusage->ru_utime.tv_usec);
++
++ __put_user(rusage->ru_stime.tv_sec, &target_rusage->ru_stime.tv_sec);
++ __put_user(rusage->ru_stime.tv_usec, &target_rusage->ru_stime.tv_usec);
++
++ __put_user(rusage->ru_maxrss, &target_rusage->ru_maxrss);
++ __put_user(rusage->ru_idrss, &target_rusage->ru_idrss);
++ __put_user(rusage->ru_idrss, &target_rusage->ru_idrss);
++ __put_user(rusage->ru_isrss, &target_rusage->ru_isrss);
++ __put_user(rusage->ru_minflt, &target_rusage->ru_minflt);
++ __put_user(rusage->ru_majflt, &target_rusage->ru_majflt);
++ __put_user(rusage->ru_nswap, &target_rusage->ru_nswap);
++ __put_user(rusage->ru_inblock, &target_rusage->ru_inblock);
++ __put_user(rusage->ru_oublock, &target_rusage->ru_oublock);
++ __put_user(rusage->ru_msgsnd, &target_rusage->ru_msgsnd);
++ __put_user(rusage->ru_msgrcv, &target_rusage->ru_msgrcv);
++ __put_user(rusage->ru_nsignals, &target_rusage->ru_nsignals);
++ __put_user(rusage->ru_nvcsw, &target_rusage->ru_nvcsw);
++ __put_user(rusage->ru_nivcsw, &target_rusage->ru_nivcsw);
++ unlock_user_struct(target_rusage, target_addr, 1);
++
++ return 0;
++}
++
++/*
++ * wait status conversion.
++ *
++ * Map host to target signal numbers for the wait family of syscalls.
++ * Assume all other status bits are the same.
++ */
++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;
++}
++
+diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h
+new file mode 100644
+index 0000000..d1c732a
+--- /dev/null
++++ b/bsd-user/bsd-proc.h
+@@ -0,0 +1,434 @@
++/*
++ * process related system call shims and definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __BSD_PROC_H_
++#define __BSD_PROC_H_
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/time.h>
++#include <sys/resource.h>
++#include <unistd.h>
++
++#include "qemu-bsd.h"
++
++extern int _getlogin(char*, int);
++
++/* exit(2) */
++static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1)
++{
++#ifdef TARGET_GPROF
++ _mcleanup();
++#endif
++ gdb_exit(cpu_env, arg1);
++ /* XXX: should free thread stack and CPU env here */
++ _exit(arg1);
++
++ return 0;
++}
++
++/* getgroups(2) */
++static inline abi_long do_bsd_getgroups(abi_long gidsetsize, abi_long arg2)
++{
++ abi_long ret;
++ uint32_t *target_grouplist;
++ gid_t *grouplist;
++ int i;
++
++ grouplist = alloca(gidsetsize * sizeof(gid_t));
++ ret = get_errno(getgroups(gidsetsize, grouplist));
++ if (gidsetsize != 0) {
++ if (!is_error(ret)) {
++ target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
++ if (!target_grouplist) {
++ return -TARGET_EFAULT;
++ }
++ for (i = 0; i < ret; i++) {
++ target_grouplist[i] = tswap32(grouplist[i]);
++ }
++ unlock_user(target_grouplist, arg2, gidsetsize * 2);
++ }
++ }
++ return ret;
++}
++
++/* setgroups(2) */
++static inline abi_long do_bsd_setgroups(abi_long gidsetsize, abi_long arg2)
++{
++ 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) {
++ return -TARGET_EFAULT;
++ }
++ for (i = 0; i < gidsetsize; i++) {
++ grouplist[i] = tswap32(target_grouplist[i]);
++ }
++ unlock_user(target_grouplist, arg2, 0);
++ return get_errno(setgroups(gidsetsize, grouplist));
++}
++
++/* umask(2) */
++static inline abi_long do_bsd_umask(abi_long arg1)
++{
++
++ return get_errno(umask(arg1));
++}
++
++/* setlogin(2) */
++static inline abi_long do_bsd_setlogin(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(setlogin(p));
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* getlogin(2) */
++static inline abi_long do_bsd_getlogin(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(_getlogin(p, arg2));
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* getrusage(2) */
++static inline abi_long do_bsd_getrusage(abi_long who, abi_ulong target_addr)
++{
++ abi_long ret;
++ struct rusage rusage;
++
++ ret = get_errno(getrusage(who, &rusage));
++ if (!is_error(ret)) {
++ host_to_target_rusage(target_addr, &rusage);
++ }
++ return ret;
++}
++
++/* getrlimit(2) */
++static inline abi_long do_bsd_getrlimit(abi_long arg1, abi_ulong arg2)
++{
++ abi_long ret;
++ int resource = target_to_host_resource(arg1);
++ struct target_rlimit *target_rlim;
++ struct rlimit rlim;
++
++ switch (resource) {
++ case RLIMIT_STACK:
++ rlim.rlim_cur = target_dflssiz;
++ rlim.rlim_max = target_maxssiz;
++ ret = 0;
++ break;
++
++ case RLIMIT_DATA:
++ rlim.rlim_cur = target_dfldsiz;
++ rlim.rlim_max = target_maxdsiz;
++ ret = 0;
++ break;
++
++ default:
++ ret = get_errno(getrlimit(resource, &rlim));
++ break;
++ }
++ if (!is_error(ret)) {
++ if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) {
++ return -TARGET_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);
++ }
++ return ret;
++}
++
++/* setrlimit(2) */
++static inline abi_long do_bsd_setrlimit(abi_long arg1, abi_ulong arg2)
++{
++ abi_long ret;
++ int resource = target_to_host_resource(arg1);
++ struct target_rlimit *target_rlim;
++ struct rlimit 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)) {
++ return -TARGET_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));
++ }
++ return ret;
++}
++
++/* getpid(2) */
++static inline abi_long do_bsd_getpid(void)
++{
++
++ return get_errno(getpid());
++}
++
++/* getppid(2) */
++static inline abi_long do_bsd_getppid(void)
++{
++
++ return get_errno(getppid());
++}
++
++/* getuid(2) */
++static inline abi_long do_bsd_getuid(void)
++{
++
++ return get_errno(getuid());
++}
++
++/* geteuid(2) */
++static inline abi_long do_bsd_geteuid(void)
++{
++
++ return get_errno(geteuid());
++}
++
++/* getgid(2) */
++static inline abi_long do_bsd_getgid(void)
++{
++
++ return get_errno(getgid());
++}
++
++/* getegid(2) */
++static inline abi_long do_bsd_getegid(void)
++{
++
++ return get_errno(getegid());
++}
++
++/* setuid(2) */
++static inline abi_long do_bsd_setuid(abi_long arg1)
++{
++
++ return get_errno(setuid(arg1));
++}
++
++/* seteuid(2) */
++static inline abi_long do_bsd_seteuid(abi_long arg1)
++{
++
++ return get_errno(seteuid(arg1));
++}
++
++/* setgid(2) */
++static inline abi_long do_bsd_setgid(abi_long arg1)
++{
++
++ return get_errno(setgid(arg1));
++}
++
++/* setegid(2) */
++static inline abi_long do_bsd_setegid(abi_long arg1)
++{
++
++ return get_errno(setegid(arg1));
++}
++
++/* getpgrp(2) */
++static inline abi_long do_bsd_getpgrp(void)
++{
++
++ return get_errno(getpgrp());
++}
++
++/* setreuid(2) */
++static inline abi_long do_bsd_setreuid(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(setreuid(arg1, arg2));
++}
++
++/* setregid(2) */
++static inline abi_long do_bsd_setregid(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(setregid(arg1, arg2));
++}
++
++/* setresuid(2) */
++static inline abi_long do_bsd_setresuid(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ return get_errno(setresuid(arg1, arg2, arg3));
++}
++
++/* getresuid(2) */
++static inline abi_long do_bsd_getresuid(abi_ulong arg1, abi_ulong arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ uid_t ruid, euid, suid;
++
++ ret = get_errno(getresuid(&ruid, &euid, &suid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ if (put_user_s32(ruid, arg1)) {
++ return -TARGET_EFAULT;
++ }
++ if (put_user_s32(euid, arg2)) {
++ return -TARGET_EFAULT;
++ }
++ if (put_user_s32(suid, arg3)) {
++ return -TARGET_EFAULT;
++ }
++ return ret;
++}
++
++/* getresgid(2) */
++static inline abi_long do_bsd_getresgid(abi_ulong arg1, abi_ulong arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ uid_t ruid, euid, suid;
++
++ ret = get_errno(getresgid(&ruid, &euid, &suid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ if (put_user_s32(ruid, arg1)) {
++ return -TARGET_EFAULT;
++ }
++ if (put_user_s32(euid, arg2)) {
++ return -TARGET_EFAULT;
++ }
++ if (put_user_s32(suid, arg3)) {
++ return -TARGET_EFAULT;
++ }
++ return ret;
++}
++
++/* getsid(2) */
++static inline abi_long do_bsd_getsid(abi_long arg1)
++{
++
++ return get_errno(getsid(arg1));
++}
++
++/* setsid(2) */
++static inline abi_long do_bsd_setsid(void)
++{
++
++ return get_errno(setsid());
++}
++
++/* issetugid(2) */
++static inline abi_long do_bsd_issetugid(void)
++{
++
++ return get_errno(issetugid());
++}
++
++/* profil(2) */
++static inline abi_long do_bsd_profil(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall profil()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* ktrace(2) */
++static inline abi_long do_bsd_ktrace(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall ktrace()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* utrace(2) */
++static inline abi_long do_bsd_utrace(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall ptrace()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* ptrace(2) */
++static inline abi_long do_bsd_ptrace(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall ptrace()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getpriority(2) */
++static inline abi_long do_bsd_getpriority(abi_long which, abi_long who)
++{
++ abi_long ret;
++ /*
++ * Note that negative values are valid for getpriority, so we must
++ * differentiate based on errno settings.
++ */
++ errno = 0;
++ ret = getpriority(which, who);
++ if (ret == -1 && errno != 0) {
++ ret = -host_to_target_errno(errno);
++ return ret;
++ }
++ /* Return value is a biased priority to avoid negative numbers. */
++ ret = 20 - ret;
++
++ return ret;
++}
++
++/* setpriority(2) */
++static inline abi_long do_bsd_setpriority(abi_long which, abi_long who,
++ abi_long prio)
++{
++
++ return get_errno(setpriority(which, who, prio));
++}
++
++
++#endif /* !__BSD_PROC_H_ */
++
+diff --git a/bsd-user/bsd-signal.h b/bsd-user/bsd-signal.h
+new file mode 100644
+index 0000000..48a8b56
+--- /dev/null
++++ b/bsd-user/bsd-signal.h
+@@ -0,0 +1,232 @@
++/*
++ * signal related system call shims
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __BSD_SIGNAL_H_
++#define __BSD_SIGNAL_H_
++
++/* sigaction(2) */
++static inline abi_long do_bsd_sigaction(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++ abi_long ret;
++ struct target_sigaction *old_act, act, oact, *pact;
++
++ if (arg2) {
++ if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) {
++ return -TARGET_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)) {
++ return -TARGET_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);
++ }
++ return ret;
++}
++
++
++/* sigprocmask(2) */
++static inline abi_long do_bsd_sigprocmask(abi_long arg1, abi_ulong arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ void *p;
++ 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:
++ return -TARGET_EFAULT;
++ }
++ p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
++ if (p == NULL) {
++ return -TARGET_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) {
++ p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ host_to_target_sigset(p, &oldset);
++ unlock_user(p, arg3, sizeof(target_sigset_t));
++ }
++ return ret;
++}
++
++/* sigpending(2) */
++static inline abi_long do_bsd_sigpending(abi_long arg1)
++{
++ abi_long ret;
++ void *p;
++ sigset_t set;
++
++ ret = get_errno(sigpending(&set));
++ if (!is_error(ret)) {
++ p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ host_to_target_sigset(p, &set);
++ unlock_user(p, arg1, sizeof(target_sigset_t));
++ }
++ return ret;
++}
++
++/* sigsuspend(2) */
++static inline abi_long do_bsd_sigsuspend(abi_long arg1, abi_long arg2)
++{
++ void *p;
++ sigset_t set;
++
++ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ target_to_host_sigset(&set, p);
++ unlock_user(p, arg1, 0);
++
++ return get_errno(sigsuspend(&set));
++}
++
++/* sigreturn(2) */
++static inline abi_long do_bsd_sigreturn(void *cpu_env, abi_long arg1)
++{
++
++ return do_sigreturn(cpu_env, arg1);
++}
++
++/* sigvec(2) - not defined */
++/* sigblock(2) - not defined */
++/* sigsetmask(2) - not defined */
++/* sigstack(2) - not defined */
++
++/* sigwait(2) */
++static inline abi_long do_bsd_sigwait(abi_ulong arg1, abi_ulong arg2,
++ abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++ sigset_t set;
++ int sig;
++
++ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ target_to_host_sigset(&set, p);
++ unlock_user(p, arg1, 0);
++ ret = get_errno(sigwait(&set, &sig));
++ if (!is_error(ret) && arg2) {
++ ret = put_user_s32(sig, arg2);
++ }
++ return ret;
++}
++
++/* sigwaitinfo(2) */
++static inline abi_long do_bsd_sigwaitinfo(abi_ulong arg1, abi_ulong arg2)
++{
++ abi_long ret;
++ void *p;
++ sigset_t set;
++ siginfo_t uinfo;
++
++ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ target_to_host_sigset(&set, p);
++ unlock_user(p, arg1, 0);
++ ret = get_errno(sigwaitinfo(&set, &uinfo));
++ if (!is_error(ret) && arg2) {
++ p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ host_to_target_siginfo(p, &uinfo);
++ unlock_user(p, arg2, sizeof(target_siginfo_t));
++ }
++ return ret;
++}
++
++/* sigqueue(2) */
++static inline abi_long do_bsd_sigqueue(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++ union sigval value;
++
++ value.sival_ptr = (void *)(uintptr_t)arg3;
++ return get_errno(sigqueue(arg1, target_to_host_signal(arg2), value));
++}
++
++/* sigaltstck(2) */
++static inline abi_long do_bsd_sigaltstack(void *cpu_env, abi_ulong arg1,
++ abi_ulong arg2)
++{
++
++ return do_sigaltstack(arg1, arg2, get_sp_from_cpustate(cpu_env));
++}
++
++/* kill(2) */
++static inline abi_long do_bsd_kill(abi_long pid, abi_long sig)
++{
++
++ return get_errno(kill(pid, target_to_host_signal(sig)));
++}
++
++/* killpg(2) */
++static inline abi_long do_bsd_killpg(abi_long pg, abi_long sig)
++{
++
++ return get_errno(killpg(pg, target_to_host_signal(sig)));
++}
++
++#endif /* ! __BSD_SIGNAL_H_ */
+diff --git a/bsd-user/bsd-socket.c b/bsd-user/bsd-socket.c
+new file mode 100644
+index 0000000..c1a3b49
+--- /dev/null
++++ b/bsd-user/bsd-socket.c
+@@ -0,0 +1,108 @@
++/*
++ * BSD socket system call related helpers
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <netinet/in.h>
++
++#include "qemu.h"
++#include "qemu-bsd.h"
++
++/*
++ * socket conversion
++ */
++abi_long target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
++ socklen_t len)
++{
++ const socklen_t unix_maxlen = sizeof(struct sockaddr_un);
++ sa_family_t sa_family;
++ struct target_sockaddr *target_saddr;
++
++ target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
++ if (target_saddr == 0) {
++ return -TARGET_EFAULT;
++ }
++
++ sa_family = 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 (target_saddr->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; /* type uint8_t */
++ addr->sa_len = target_saddr->sa_len; /* type uint8_t */
++ unlock_user(target_saddr, target_addr, 0);
++
++ return 0;
++}
++
++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 == 0) {
++ return -TARGET_EFAULT;
++ }
++ memcpy(target_saddr, addr, len);
++ 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;
++}
++
++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 == 0) {
++ 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;
++}
++
+diff --git a/bsd-user/bsd-socket.h b/bsd-user/bsd-socket.h
+new file mode 100644
+index 0000000..f5d1ac8
+--- /dev/null
++++ b/bsd-user/bsd-socket.h
+@@ -0,0 +1,266 @@
++/*
++ * socket related system call shims
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef __BSD_SOCKET_H_
++#define __BSD_SOCKET_H_
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <netinet/in.h>
++
++#include "qemu-bsd.h"
++
++/* bind(2) */
++static inline abi_long do_bsd_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 (is_error(ret)) {
++ return ret;
++ }
++
++ return get_errno(bind(sockfd, addr, addrlen));
++}
++
++/* connect(2) */
++static inline abi_long do_bsd_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 (is_error(ret)) {
++ return ret;
++ }
++
++ return get_errno(connect(sockfd, addr, addrlen));
++}
++
++/* accept(2) */
++static inline abi_long do_bsd_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;
++}
++
++/* getpeername(2) */
++static inline abi_long do_bsd_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;
++}
++
++/* getsockname(2) */
++static inline abi_long do_bsd_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;
++}
++
++/* socketpair(2) */
++static inline abi_long do_bsd_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;
++}
++
++/* sendto(2) */
++static inline abi_long do_bsd_sendto(int fd, abi_ulong msg, size_t len,
++ int flags, abi_ulong target_addr, socklen_t addrlen)
++{
++ struct sockaddr *saddr;
++ 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) {
++ saddr = alloca(addrlen);
++ ret = target_to_host_sockaddr(saddr, target_addr, addrlen);
++ if (is_error(ret)) {
++ unlock_user(host_msg, msg, 0);
++ return ret;
++ }
++ ret = get_errno(sendto(fd, host_msg, len, flags, saddr, addrlen));
++ } else {
++ ret = get_errno(send(fd, host_msg, len, flags));
++ }
++ unlock_user(host_msg, msg, 0);
++ return ret;
++}
++
++/* recvfrom(2) */
++static inline abi_long do_bsd_recvfrom(int fd, abi_ulong msg, size_t len,
++ int flags, abi_ulong target_addr, abi_ulong target_addrlen)
++{
++ socklen_t addrlen;
++ struct sockaddr *saddr;
++ 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;
++ }
++ saddr = alloca(addrlen);
++ ret = get_errno(recvfrom(fd, host_msg, len, flags, saddr, &addrlen));
++ } else {
++ 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, saddr, 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;
++}
++
++/* socket(2) */
++static inline abi_long do_bsd_socket(abi_long domain, abi_long type,
++ abi_long protocol)
++{
++
++ return get_errno(socket(domain, type, protocol));
++}
++
++/* shutdown(2) */
++static inline abi_long do_bsd_shutdown(abi_long s, abi_long how)
++{
++
++ return get_errno(shutdown(s, how));
++}
++
++#endif /* !__BSD_SOCKET_H_ */
+diff --git a/bsd-user/bsdload.c b/bsd-user/bsdload.c
+index 2abc713..45fdcf8 100644
+--- a/bsd-user/bsdload.c
++++ b/bsd-user/bsdload.c
+@@ -1,4 +1,19 @@
+-/* Code for loading BSD executables. Mostly linux kernel code. */
++/*
++ * Load BSD executables.
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
+
+ #include <sys/types.h>
+ #include <sys/stat.h>
+@@ -26,38 +41,22 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src,
+ return 0;
+ }
+
+-static int in_group_p(gid_t g)
+-{
+- /* return TRUE if we're in the specified group, FALSE otherwise */
+- int ngroup;
+- int i;
+- gid_t grouplist[TARGET_NGROUPS];
+-
+- ngroup = getgroups(TARGET_NGROUPS, grouplist);
+- for(i = 0; i < ngroup; i++) {
+- if(grouplist[i] == g) {
+- return 1;
+- }
+- }
+- return 0;
+-}
+-
+ static int count(char ** vec)
+ {
+ int i;
+
+- for(i = 0; *vec; i++) {
++ for (i = 0; *vec; i++) {
+ vec++;
+ }
+
+ return(i);
+ }
+
+-static int prepare_binprm(struct linux_binprm *bprm)
++static int prepare_binprm(struct bsd_binprm *bprm)
+ {
+ struct stat st;
+ int mode;
+- int retval, id_change;
++ int retval;
+
+ if(fstat(bprm->fd, &st) < 0) {
+ return(-errno);
+@@ -73,14 +72,10 @@ static int prepare_binprm(struct linux_binprm *bprm)
+
+ bprm->e_uid = geteuid();
+ bprm->e_gid = getegid();
+- id_change = 0;
+
+ /* Set-uid? */
+ if(mode & S_ISUID) {
+ bprm->e_uid = st.st_uid;
+- if(bprm->e_uid != geteuid()) {
+- id_change = 1;
+- }
+ }
+
+ /* Set-gid? */
+@@ -91,9 +86,6 @@ static int prepare_binprm(struct linux_binprm *bprm)
+ */
+ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
+ bprm->e_gid = st.st_gid;
+- if (!in_group_p(bprm->e_gid)) {
+- id_change = 1;
+- }
+ }
+
+ memset(bprm->buf, 0, sizeof(bprm->buf));
+@@ -154,34 +146,116 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp,
+ return sp;
+ }
+
++static int is_there(const char *candidate)
++{
++ struct stat fin;
++
++ /* XXX work around access(2) false positives for superuser */
++ if (access(candidate, X_OK) == 0 && stat(candidate, &fin) == 0 &&
++ S_ISREG(fin.st_mode) && (getuid() != 0 ||
++ (fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) {
++ return 1;
++ }
++
++ return 0;
++}
++
++static int find_in_path(char *path, const char *filename, char *retpath,
++ size_t rpsize)
++{
++ const char *d;
++ int found;
++
++ if (strchr(filename, '/') != NULL) {
++ if (is_there(filename)) {
++ if (!realpath(filename, retpath)) {
++ return -1;
++ }
++ return 0;
++ } else {
++ return -1;
++ }
++ }
++
++ found = 0;
++ while ((d = strsep(&path, ":")) != NULL) {
++ if (*d == '\0') {
++ d = ".";
++ }
++ if (snprintf(retpath, rpsize, "%s/%s", d, filename) >= (int)rpsize) {
++ continue;
++ }
++ if (is_there((const char *)retpath)) {
++ found = 1;
++ break;
++ }
++ }
++ return found;
++}
++
+ 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;
++ char *p, *path = NULL, fullpath[PATH_MAX];
++ const char *execname = NULL;
++ int retval, i, found;
+
+- bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
++ bprm->p = TARGET_PAGE_SIZE * MAX_ARG_PAGES; /* -sizeof(unsigned int); */
+ for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
+- bprm.page[i] = NULL;
+- retval = open(filename, O_RDONLY);
+- if (retval < 0)
++ bprm->page[i] = NULL;
++
++ /* Find target executable in path, if not already an absolute path. */
++ p = getenv("PATH");
++ if (p != NULL) {
++ path = g_strdup(p);
++ if (path == NULL) {
++ fprintf(stderr, "Out of memory\n");
++ return -1;
++ }
++ execname = realpath(filename, NULL);
++ if (execname == NULL) {
++ execname = g_strdup(filename);
++ }
++ found = find_in_path(path, execname, fullpath, sizeof(fullpath));
++ /* Absolute path specified but not found? */
++ if (found == -1) {
++ return -1;
++ }
++ if (found) {
++ retval = open(fullpath, O_RDONLY);
++ bprm->fullpath = g_strdup(fullpath);
++ } else {
++ retval = open(execname, O_RDONLY);
++ bprm->fullpath = NULL;
++ }
++ if (execname) {
++ g_free((void *)execname);
++ }
++ g_free(path);
++ } else {
++ retval = open(filename, O_RDONLY);
++ bprm->fullpath = NULL;
++ }
++ 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 +270,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 93fd9e4..ef96b8c 100644
+--- a/bsd-user/elfload.c
++++ b/bsd-user/elfload.c
+@@ -1,4 +1,20 @@
+-/* This is the Linux kernel elf-loading code, ported into user space */
++/*
++ * ELF loading code
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
+
+ #include <stdio.h>
+ #include <sys/types.h>
+@@ -11,544 +27,12 @@
+
+ #include "qemu.h"
+ #include "disas/disas.h"
++#include "target_os_elf.h"
++#include "target_os_stack.h"
++#include "target_os_thread.h"
+
+-#ifdef _ARCH_PPC64
+-#undef ARCH_DLINFO
+-#undef ELF_PLATFORM
+-#undef ELF_HWCAP
+-#undef ELF_CLASS
+-#undef ELF_DATA
+-#undef ELF_ARCH
+-#endif
+-
+-/* from personality.h */
+-
+-/*
+- * Flags for bug emulation.
+- *
+- * These occupy the top three bytes.
+- */
+-enum {
+- ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
+- FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors
+- * (signal handling)
+- */
+- MMAP_PAGE_ZERO = 0x0100000,
+- ADDR_COMPAT_LAYOUT = 0x0200000,
+- READ_IMPLIES_EXEC = 0x0400000,
+- ADDR_LIMIT_32BIT = 0x0800000,
+- SHORT_INODE = 0x1000000,
+- WHOLE_SECONDS = 0x2000000,
+- STICKY_TIMEOUTS = 0x4000000,
+- ADDR_LIMIT_3GB = 0x8000000,
+-};
+-
+-/*
+- * Personality types.
+- *
+- * These go in the low byte. Avoid using the top bit, it will
+- * conflict with error returns.
+- */
+-enum {
+- PER_LINUX = 0x0000,
+- PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
+- PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
+- PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+- PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
+- PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS |
+- WHOLE_SECONDS | SHORT_INODE,
+- PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
+- PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
+- PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
+- PER_BSD = 0x0006,
+- PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
+- PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
+- PER_LINUX32 = 0x0008,
+- PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
+- PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
+- PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
+- PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
+- PER_RISCOS = 0x000c,
+- PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
+- PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
+- PER_OSF4 = 0x000f, /* OSF/1 v4 */
+- PER_HPUX = 0x0010,
+- PER_MASK = 0x00ff,
+-};
+-
+-/*
+- * Return the base personality without flags.
+- */
+-#define personality(pers) (pers & PER_MASK)
+-
+-/* this flag is uneffective under linux too, should be deleted */
+-#ifndef MAP_DENYWRITE
+-#define MAP_DENYWRITE 0
+-#endif
+-
+-/* should probably go in elf.h */
+-#ifndef ELIBBAD
+-#define ELIBBAD 80
+-#endif
+-
+-#ifdef TARGET_I386
+-
+-#define ELF_PLATFORM get_elf_platform()
+-
+-static const char *get_elf_platform(void)
+-{
+- static char elf_platform[] = "i386";
+- int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL);
+- if (family > 6)
+- family = 6;
+- if (family >= 3)
+- elf_platform[1] = '0' + family;
+- return elf_platform;
+-}
+-
+-#define ELF_HWCAP get_elf_hwcap()
+-
+-static uint32_t get_elf_hwcap(void)
+-{
+- X86CPU *cpu = X86_CPU(thread_cpu);
+-
+- return cpu->env.features[FEAT_1_EDX];
+-}
+-
+-#ifdef TARGET_X86_64
+-#define ELF_START_MMAP 0x2aaaaab000ULL
+-#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
+-
+-#define ELF_CLASS ELFCLASS64
+-#define ELF_DATA ELFDATA2LSB
+-#define ELF_ARCH EM_X86_64
+-
+-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+-{
+- regs->rax = 0;
+- regs->rsp = infop->start_stack;
+- regs->rip = infop->entry;
+- if (bsd_type == target_freebsd) {
+- regs->rdi = infop->start_stack;
+- }
+-}
+-
+-#else
+-
+-#define ELF_START_MMAP 0x80000000
+-
+-/*
+- * This is used to ensure we don't load something for the wrong architecture.
+- */
+-#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
+-
+-/*
+- * These are used to set parameters in the core dumps.
+- */
+-#define ELF_CLASS ELFCLASS32
+-#define ELF_DATA ELFDATA2LSB
+-#define ELF_ARCH EM_386
+-
+-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+-{
+- regs->esp = infop->start_stack;
+- regs->eip = infop->entry;
+-
+- /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
+- starts %edx contains a pointer to a function which might be
+- registered using `atexit'. This provides a mean for the
+- dynamic linker to call DT_FINI functions for shared libraries
+- that have been loaded before the code runs.
+-
+- A value of 0 tells we have no such handler. */
+- regs->edx = 0;
+-}
+-#endif
+-
+-#define USE_ELF_CORE_DUMP
+-#define ELF_EXEC_PAGESIZE 4096
+-
+-#endif
+-
+-#ifdef TARGET_ARM
+-
+-#define ELF_START_MMAP 0x80000000
+-
+-#define elf_check_arch(x) ( (x) == EM_ARM )
+-
+-#define ELF_CLASS ELFCLASS32
+-#ifdef TARGET_WORDS_BIGENDIAN
+-#define ELF_DATA ELFDATA2MSB
+-#else
+-#define ELF_DATA ELFDATA2LSB
+-#endif
+-#define ELF_ARCH EM_ARM
+-
+-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+-{
+- abi_long stack = infop->start_stack;
+- memset(regs, 0, sizeof(*regs));
+- regs->ARM_cpsr = 0x10;
+- if (infop->entry & 1)
+- regs->ARM_cpsr |= CPSR_T;
+- regs->ARM_pc = infop->entry & 0xfffffffe;
+- regs->ARM_sp = infop->start_stack;
+- /* FIXME - what to for failure of get_user()? */
+- get_user_ual(regs->ARM_r2, stack + 8); /* envp */
+- get_user_ual(regs->ARM_r1, stack + 4); /* envp */
+- /* XXX: it seems that r0 is zeroed after ! */
+- regs->ARM_r0 = 0;
+- /* For uClinux PIC binaries. */
+- /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
+- regs->ARM_r10 = infop->start_data;
+-}
+-
+-#define USE_ELF_CORE_DUMP
+-#define ELF_EXEC_PAGESIZE 4096
+-
+-enum
+-{
+- ARM_HWCAP_ARM_SWP = 1 << 0,
+- ARM_HWCAP_ARM_HALF = 1 << 1,
+- ARM_HWCAP_ARM_THUMB = 1 << 2,
+- ARM_HWCAP_ARM_26BIT = 1 << 3,
+- ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
+- ARM_HWCAP_ARM_FPA = 1 << 5,
+- ARM_HWCAP_ARM_VFP = 1 << 6,
+- ARM_HWCAP_ARM_EDSP = 1 << 7,
+-};
+-
+-#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \
+- | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \
+- | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP)
+-
+-#endif
+-
+-#ifdef TARGET_SPARC
+-#ifdef TARGET_SPARC64
+-
+-#define ELF_START_MMAP 0x80000000
+-
+-#ifndef TARGET_ABI32
+-#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
+-#else
+-#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
+-#endif
+-
+-#define ELF_CLASS ELFCLASS64
+-#define ELF_DATA ELFDATA2MSB
+-#define ELF_ARCH EM_SPARCV9
+-
+-#define STACK_BIAS 2047
+-
+-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+-{
+-#ifndef TARGET_ABI32
+- regs->tstate = 0;
+-#endif
+- regs->pc = infop->entry;
+- regs->npc = regs->pc + 4;
+- regs->y = 0;
+-#ifdef TARGET_ABI32
+- regs->u_regs[14] = infop->start_stack - 16 * 4;
+-#else
+- if (personality(infop->personality) == PER_LINUX32)
+- regs->u_regs[14] = infop->start_stack - 16 * 4;
+- else {
+- regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
+- if (bsd_type == target_freebsd) {
+- regs->u_regs[8] = infop->start_stack;
+- regs->u_regs[11] = infop->start_stack;
+- }
+- }
+-#endif
+-}
+-
+-#else
+-#define ELF_START_MMAP 0x80000000
+-
+-#define elf_check_arch(x) ( (x) == EM_SPARC )
+-
+-#define ELF_CLASS ELFCLASS32
+-#define ELF_DATA ELFDATA2MSB
+-#define ELF_ARCH EM_SPARC
+-
+-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+-{
+- regs->psr = 0;
+- regs->pc = infop->entry;
+- regs->npc = regs->pc + 4;
+- regs->y = 0;
+- regs->u_regs[14] = infop->start_stack - 16 * 4;
+-}
+-
+-#endif
+-#endif
+-
+-#ifdef TARGET_PPC
+-
+-#define ELF_START_MMAP 0x80000000
+-
+-#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+-
+-#define elf_check_arch(x) ( (x) == EM_PPC64 )
+-
+-#define ELF_CLASS ELFCLASS64
+-
+-#else
+-
+-#define elf_check_arch(x) ( (x) == EM_PPC )
+-
+-#define ELF_CLASS ELFCLASS32
+-
+-#endif
+-
+-#ifdef TARGET_WORDS_BIGENDIAN
+-#define ELF_DATA ELFDATA2MSB
+-#else
+-#define ELF_DATA ELFDATA2LSB
+-#endif
+-#define ELF_ARCH EM_PPC
+-
+-/*
+- * We need to put in some extra aux table entries to tell glibc what
+- * the cache block size is, so it can use the dcbz instruction safely.
+- */
+-#define AT_DCACHEBSIZE 19
+-#define AT_ICACHEBSIZE 20
+-#define AT_UCACHEBSIZE 21
+-/* A special ignored type value for PPC, for glibc compatibility. */
+-#define AT_IGNOREPPC 22
+-/*
+- * The requirements here are:
+- * - keep the final alignment of sp (sp & 0xf)
+- * - make sure the 32-bit value at the first 16 byte aligned position of
+- * AUXV is greater than 16 for glibc compatibility.
+- * AT_IGNOREPPC is used for that.
+- * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
+- * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
+- */
+-#define DLINFO_ARCH_ITEMS 5
+-#define ARCH_DLINFO \
+-do { \
+- NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \
+- NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \
+- NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
+- /* \
+- * Now handle glibc compatibility. \
+- */ \
+- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
+- } while (0)
+-
+-static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
+-{
+- abi_ulong pos = infop->start_stack;
+- abi_ulong tmp;
+-#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+- abi_ulong entry, toc;
+-#endif
+-
+- _regs->gpr[1] = infop->start_stack;
+-#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
+- entry = ldq_raw(infop->entry) + infop->load_addr;
+- toc = ldq_raw(infop->entry + 8) + infop->load_addr;
+- _regs->gpr[2] = toc;
+- infop->entry = entry;
+-#endif
+- _regs->nip = infop->entry;
+- /* Note that isn't exactly what regular kernel does
+- * but this is what the ABI wants and is needed to allow
+- * execution of PPC BSD programs.
+- */
+- /* FIXME - what to for failure of get_user()? */
+- get_user_ual(_regs->gpr[3], pos);
+- pos += sizeof(abi_ulong);
+- _regs->gpr[4] = pos;
+- for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong))
+- tmp = ldl(pos);
+- _regs->gpr[5] = pos;
+-}
+-
+-#define USE_ELF_CORE_DUMP
+-#define ELF_EXEC_PAGESIZE 4096
+-
+-#endif
+-
+-#ifdef TARGET_MIPS
+-
+-#define ELF_START_MMAP 0x80000000
+-
+-#define elf_check_arch(x) ( (x) == EM_MIPS )
+-
+-#ifdef TARGET_MIPS64
+-#define ELF_CLASS ELFCLASS64
+-#else
+-#define ELF_CLASS ELFCLASS32
+-#endif
+-#ifdef TARGET_WORDS_BIGENDIAN
+-#define ELF_DATA ELFDATA2MSB
+-#else
+-#define ELF_DATA ELFDATA2LSB
+-#endif
+-#define ELF_ARCH EM_MIPS
+-
+-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;
+-}
+-
+-#define USE_ELF_CORE_DUMP
+-#define ELF_EXEC_PAGESIZE 4096
+-
+-#endif /* TARGET_MIPS */
+-
+-#ifdef TARGET_SH4
+-
+-#define ELF_START_MMAP 0x80000000
+-
+-#define elf_check_arch(x) ( (x) == EM_SH )
+-
+-#define ELF_CLASS ELFCLASS32
+-#define ELF_DATA ELFDATA2LSB
+-#define ELF_ARCH EM_SH
+-
+-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+-{
+- /* Check other registers XXXXX */
+- regs->pc = infop->entry;
+- regs->regs[15] = infop->start_stack;
+-}
+-
+-#define USE_ELF_CORE_DUMP
+-#define ELF_EXEC_PAGESIZE 4096
+-
+-#endif
+-
+-#ifdef TARGET_CRIS
+-
+-#define ELF_START_MMAP 0x80000000
+-
+-#define elf_check_arch(x) ( (x) == EM_CRIS )
+-
+-#define ELF_CLASS ELFCLASS32
+-#define ELF_DATA ELFDATA2LSB
+-#define ELF_ARCH EM_CRIS
+-
+-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+-{
+- regs->erp = infop->entry;
+-}
+-
+-#define USE_ELF_CORE_DUMP
+-#define ELF_EXEC_PAGESIZE 8192
+-
+-#endif
+-
+-#ifdef TARGET_M68K
+-
+-#define ELF_START_MMAP 0x80000000
+-
+-#define elf_check_arch(x) ( (x) == EM_68K )
+-
+-#define ELF_CLASS ELFCLASS32
+-#define ELF_DATA ELFDATA2MSB
+-#define ELF_ARCH EM_68K
+-
+-/* ??? Does this need to do anything?
+-#define ELF_PLAT_INIT(_r) */
+-
+-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+-{
+- regs->usp = infop->start_stack;
+- regs->sr = 0;
+- regs->pc = infop->entry;
+-}
+-
+-#define USE_ELF_CORE_DUMP
+-#define ELF_EXEC_PAGESIZE 8192
+-
+-#endif
+-
+-#ifdef TARGET_ALPHA
+-
+-#define ELF_START_MMAP (0x30000000000ULL)
+-
+-#define elf_check_arch(x) ( (x) == ELF_ARCH )
+-
+-#define ELF_CLASS ELFCLASS64
+-#define ELF_DATA ELFDATA2MSB
+-#define ELF_ARCH EM_ALPHA
+-
+-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
+-{
+- regs->pc = infop->entry;
+- regs->ps = 8;
+- regs->usp = infop->start_stack;
+- regs->unique = infop->start_data; /* ? */
+- printf("Set unique value to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n",
+- regs->unique, infop->start_data);
+-}
+-
+-#define USE_ELF_CORE_DUMP
+-#define ELF_EXEC_PAGESIZE 8192
+-
+-#endif /* TARGET_ALPHA */
+-
+-#ifndef ELF_PLATFORM
+-#define ELF_PLATFORM (NULL)
+-#endif
+-
+-#ifndef ELF_HWCAP
+-#define ELF_HWCAP 0
+-#endif
+-
+-#ifdef TARGET_ABI32
+-#undef ELF_CLASS
+-#define ELF_CLASS ELFCLASS32
+-#undef bswaptls
+-#define bswaptls(ptr) bswap32s(ptr)
+-#endif
+-
+-#include "elf.h"
+-
+-struct exec
+-{
+- unsigned int a_info; /* Use macros N_MAGIC, etc for access */
+- unsigned int a_text; /* length of text, in bytes */
+- unsigned int a_data; /* length of data, in bytes */
+- unsigned int a_bss; /* length of uninitialized data area, in bytes */
+- unsigned int a_syms; /* length of symbol table data in file, in bytes */
+- unsigned int a_entry; /* start address */
+- unsigned int a_trsize; /* length of relocation info for text, in bytes */
+- unsigned int a_drsize; /* length of relocation info for data, in bytes */
+-};
+-
+-
+-#define N_MAGIC(exec) ((exec).a_info & 0xffff)
+-#define OMAGIC 0407
+-#define NMAGIC 0410
+-#define ZMAGIC 0413
+-#define QMAGIC 0314
+-
+-/* max code+data+bss space allocated to elf interpreter */
+-#define INTERP_MAP_SIZE (32 * 1024 * 1024)
+-
+-/* max code+data+bss+brk space allocated to ET_DYN executables */
+-#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
+-
+-/* Necessary parameters */
+-#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
+-#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
+-#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
+-
+-#define INTERPRETER_NONE 0
+-#define INTERPRETER_AOUT 1
+-#define INTERPRETER_ELF 2
+-
+-#define DLINFO_ITEMS 12
++abi_ulong target_stksiz;
++abi_ulong target_stkbas;
+
+ static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
+ {
+@@ -560,7 +44,7 @@ static int load_aout_interp(void * exptr, int interp_fd);
+ #ifdef BSWAP_NEEDED
+ static void bswap_ehdr(struct elfhdr *ehdr)
+ {
+- bswap16s(&ehdr->e_type); /* Object file type */
++ bswap16s(&ehdr->e_type); /* Object file type */
+ bswap16s(&ehdr->e_machine); /* Architecture */
+ bswap32s(&ehdr->e_version); /* Object file version */
+ bswaptls(&ehdr->e_entry); /* Entry point virtual address */
+@@ -568,37 +52,45 @@ static void bswap_ehdr(struct elfhdr *ehdr)
+ bswaptls(&ehdr->e_shoff); /* Section header table file offset */
+ bswap32s(&ehdr->e_flags); /* Processor-specific flags */
+ bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
+- bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
++ bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
+ bswap16s(&ehdr->e_phnum); /* Program header table entry count */
+- bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
++ bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
+ bswap16s(&ehdr->e_shnum); /* Section header table entry count */
+- bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
++ 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 */
++ 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 */
++ }
+ }
+
+-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)
+@@ -608,7 +100,15 @@ static void bswap_sym(struct elf_sym *sym)
+ bswaptls(&sym->st_size);
+ bswap16s(&sym->st_shndx);
+ }
+-#endif
++
++#else /* ! BSWAP_NEEDED */
++
++static void bswap_ehdr(struct elfhdr *ehdr) { }
++static void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
++static void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
++static void bswap_sym(struct elf_sym *sym) { }
++
++#endif /* ! BSWAP_NEEDED */
+
+ /*
+ * 'copy_elf_strings()' copies argument/envelope strings from user
+@@ -665,42 +165,34 @@ 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,
++static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
+ struct image_info *info)
+ {
+- abi_ulong stack_base, size, error;
+- int i;
++ abi_ulong stack_base, size;
++ abi_long addr;
+
+ /* Create enough stack to hold everything. If we don't use
+ * it for args, we'll use it for something else...
+ */
+- size = x86_stack_size;
+- if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
+- size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
+- error = target_mmap(0,
+- size + qemu_host_page_size,
+- PROT_READ | PROT_WRITE,
+- MAP_PRIVATE | MAP_ANON,
+- -1, 0);
+- if (error == -1) {
++ size = target_dflssiz;
++ stack_base = TARGET_USRSTACK - size;
++ addr = target_mmap(stack_base , size + qemu_host_page_size,
++ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
++ if (addr == -1) {
+ perror("stk mmap");
+ exit(-1);
+ }
+ /* we reserve one extra page at the top of the stack as guard */
+- target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
++ target_mprotect(addr + size, qemu_host_page_size, PROT_NONE);
+
+- stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
+- p += stack_base;
++ target_stksiz = size;
++ target_stkbas = addr;
+
+- for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
+- if (bprm->page[i]) {
+- info->rss++;
+- /* FIXME - check return value of memcpy_to_target() for failure */
+- memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
+- g_free(bprm->page[i]);
+- }
+- stack_base += TARGET_PAGE_SIZE;
++ if (setup_initial_stack(bprm, &p) != 0) {
++ perror("stk setup");
++ exit(-1);
+ }
++
+ return p;
+ }
+
+@@ -758,86 +250,6 @@ static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
+ }
+ }
+
+-
+-static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
+- struct elfhdr * exec,
+- abi_ulong load_addr,
+- abi_ulong load_bias,
+- abi_ulong interp_load_addr, int ibcs,
+- struct image_info *info)
+-{
+- abi_ulong sp;
+- int size;
+- abi_ulong u_platform;
+- const char *k_platform;
+- const int n = sizeof(elf_addr_t);
+-
+- sp = p;
+- u_platform = 0;
+- k_platform = ELF_PLATFORM;
+- if (k_platform) {
+- size_t len = strlen(k_platform) + 1;
+- sp -= (len + n - 1) & ~(n - 1);
+- u_platform = sp;
+- /* FIXME - check return value of memcpy_to_target() for failure */
+- memcpy_to_target(sp, k_platform, len);
+- }
+- /*
+- * Force 16 byte _final_ alignment here for generality.
+- */
+- sp = sp &~ (abi_ulong)15;
+- size = (DLINFO_ITEMS + 1) * 2;
+- if (k_platform)
+- size += 2;
+-#ifdef DLINFO_ARCH_ITEMS
+- size += DLINFO_ARCH_ITEMS * 2;
+-#endif
+- size += envc + argc + 2;
+- size += (!ibcs ? 3 : 1); /* argc itself */
+- size *= n;
+- if (size & 15)
+- sp -= 16 - (size & 15);
+-
+- /* This is correct because Linux defines
+- * elf_addr_t as Elf32_Off / Elf64_Off
+- */
+-#define NEW_AUX_ENT(id, val) do { \
+- sp -= n; put_user_ual(val, sp); \
+- sp -= n; put_user_ual(id, sp); \
+- } while(0)
+-
+- NEW_AUX_ENT (AT_NULL, 0);
+-
+- /* There must be exactly DLINFO_ITEMS entries here. */
+- NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
+- NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
+- NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
+- NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
+- NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
+- NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
+- NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
+- NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
+- NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
+- NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
+- 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));
+- if (k_platform)
+- NEW_AUX_ENT(AT_PLATFORM, u_platform);
+-#ifdef ARCH_DLINFO
+- /*
+- * ARCH_DLINFO must come last so platform specific code can enforce
+- * special alignment requirements on the AUXV if necessary (eg. PPC).
+- */
+- ARCH_DLINFO;
+-#endif
+-#undef NEW_AUX_ENT
+-
+- sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
+- return sp;
+-}
+-
+-
+ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
+ int interpreter_fd,
+ abi_ulong *interp_load_addr)
+@@ -855,9 +267,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) ||
+@@ -898,12 +308,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
+@@ -920,54 +325,57 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
+ }
+
+ eppnt = elf_phdata;
+- for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
+- if (eppnt->p_type == PT_LOAD) {
+- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+- int elf_prot = 0;
+- abi_ulong vaddr = 0;
+- abi_ulong k;
+-
+- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
+- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
+- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
+- if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
+- elf_type |= MAP_FIXED;
+- vaddr = eppnt->p_vaddr;
+- }
+- error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
+- eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
+- elf_prot,
+- elf_type,
+- interpreter_fd,
+- eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
+-
+- if (error == -1) {
+- /* Real error */
+- close(interpreter_fd);
+- free(elf_phdata);
+- return ~((abi_ulong)0UL);
+- }
+-
+- if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
+- load_addr = error;
+- load_addr_set = 1;
++ for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++)
++ if (eppnt->p_type == PT_LOAD) {
++ int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
++ int elf_prot = 0;
++ abi_ulong vaddr = 0;
++ abi_ulong k;
++
++ if (eppnt->p_flags & PF_R) {
++ elf_prot = PROT_READ;
++ }
++ if (eppnt->p_flags & PF_W) {
++ elf_prot |= PROT_WRITE;
++ }
++ if (eppnt->p_flags & PF_X) {
++ elf_prot |= PROT_EXEC;
++ }
++ if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
++ elf_type |= MAP_FIXED;
++ vaddr = eppnt->p_vaddr;
++ }
++ error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
++ eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
++ elf_prot, elf_type, interpreter_fd, eppnt->p_offset -
++ TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
++ if (error == -1) {
++ /* Real error */
++ close(interpreter_fd);
++ free(elf_phdata);
++ return ~((abi_ulong)0UL);
++ }
++ if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
++ load_addr = error;
++ load_addr_set = 1;
++ }
++ /*
++ * Find the end of the file mapping for this phdr, and keep
++ * track of the largest address we see for this.
++ */
++ k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
++ if (k > elf_bss) {
++ elf_bss = k;
++ }
++ /*
++ * Do the same thing for the memory mapping - between
++ * elf_bss and last_bss is the bss section.
++ */
++ k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
++ if (k > last_bss) {
++ last_bss = k;
++ }
+ }
+-
+- /*
+- * Find the end of the file mapping for this phdr, and keep
+- * track of the largest address we see for this.
+- */
+- k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
+- if (k > elf_bss) elf_bss = k;
+-
+- /*
+- * Do the same thing for the memory mapping - between
+- * elf_bss and last_bss is the bss section.
+- */
+- k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
+- if (k > last_bss) last_bss = k;
+- }
+-
+ /* Now use mmap to map the library into memory. */
+
+ close(interpreter_fd);
+@@ -979,7 +387,8 @@ static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
+ * bss page.
+ */
+ padzero(elf_bss, last_bss);
+- elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
++ /* What we have mapped so far */
++ elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1);
+
+ /* Map the last of the bss segment */
+ if (last_bss > elf_bss) {
+@@ -1048,9 +457,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
+@@ -1058,9 +465,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;
+ }
+ }
+@@ -1093,9 +498,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 ||
+@@ -1147,8 +550,32 @@ static void load_symbols(struct elfhdr *hdr, int fd)
+ syminfos = s;
+ }
+
+-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+- struct image_info * info)
++/* 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)
+ {
+ struct elfhdr elf_ex;
+ struct elfhdr interp_elf_ex;
+@@ -1166,20 +593,18 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ int retval;
+ char * elf_interpreter;
+ abi_ulong elf_entry, interp_load_addr = 0;
+- int status;
+ abi_ulong start_code, end_code, start_data, end_data;
+ abi_ulong reloc_func_desc = 0;
++#ifdef LOW_ELF_STACK
+ abi_ulong elf_stack;
++#endif
+ char passed_fileno[6];
+
+ ibcs2_interpreter = 0;
+- status = 0;
+ 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) ||
+@@ -1187,12 +612,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);
+@@ -1213,19 +640,16 @@ 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;
+ elf_brk = 0;
+
+
++#ifdef LOW_ELF_STACK
+ elf_stack = ~((abi_ulong)0UL);
++#endif
+ elf_interpreter = NULL;
+ start_code = ~((abi_ulong)0UL);
+ end_code = 0;
+@@ -1233,7 +657,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ end_data = 0;
+ interp_ex.a_info = 0;
+
+- for(i=0;i < elf_ex.e_phnum; i++) {
++ for (i = 0; i < elf_ex.e_phnum; i++) {
+ if (elf_ppnt->p_type == PT_INTERP) {
+ if ( elf_interpreter != NULL )
+ {
+@@ -1271,9 +695,9 @@ int load_elf_binary(struct linux_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) {
+- ibcs2_interpreter = 1;
++ if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0 ||
++ strcmp(elf_interpreter, "/usr/lib/ld-elf.so.1") == 0) {
++ ibcs2_interpreter = 1;
+ }
+
+ #if 0
+@@ -1403,7 +827,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ * address.
+ */
+
+- for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
++ for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
+ int elf_prot = 0;
+ int elf_flags = 0;
+ abi_ulong error;
+@@ -1420,7 +844,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ } else if (elf_ex.e_type == ET_DYN) {
+ /* Try and get dynamic programs out of the way of the default mmap
+ base, as well as whatever program they might try to exec. This
+- is because the brk will follow the loader, and is not movable. */
++ is because the brk will follow the loader, and is not movable. */
+ /* NOTE: for qemu, we do a big mmap to get enough space
+ without hardcoding any address */
+ error = target_mmap(0, ET_DYN_MAP_SIZE,
+@@ -1517,7 +941,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ #ifdef LOW_ELF_STACK
+ info->start_stack = bprm->p = elf_stack - 4;
+ #endif
+- bprm->p = create_elf_tables(bprm->p,
++ bprm->p = target_create_elf_tables(bprm->p,
+ bprm->argc,
+ bprm->envc,
+ &elf_ex,
+@@ -1533,19 +957,22 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ info->end_data = end_data;
+ info->start_stack = bprm->p;
+
+- /* Calling set_brk effectively mmaps the pages that we need for the bss and break
+- sections */
++ /*
++ * Calling set_brk effectively mmaps the pages that we need for the bss
++ * and break sections.
++ */
+ set_brk(elf_bss, elf_brk);
+
+ 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 )
+@@ -1554,12 +981,21 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+ and some applications "depend" upon this behavior.
+ Since we do not have the power to recompile these, we
+ emulate the SVr4 behavior. Sigh. */
+- mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
+- MAP_FIXED | MAP_PRIVATE, -1, 0);
++ mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ |
++ PROT_EXEC, MAP_FIXED | MAP_PRIVATE, -1, 0);
++ if (mapped_addr == -1) {
++ return -1;
++ }
+ }
+
+ info->entry = elf_entry;
+
++#ifdef USE_ELF_CORE_DUMP
++ /* not yet */
++ /* bprm->core_dump = &elf_core_dump; */
++ bprm->core_dump = NULL;
++#endif
++
+ return 0;
+ }
+
+@@ -1571,5 +1007,5 @@ static int load_aout_interp(void * exptr, int interp_fd)
+
+ void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
+ {
+- init_thread(regs, infop);
++ target_thread_init(regs, infop);
+ }
+diff --git a/bsd-user/errno_defs.h b/bsd-user/errno_defs.h
+index 1efa502..f01181d 100644
+--- a/bsd-user/errno_defs.h
++++ b/bsd-user/errno_defs.h
+@@ -1,6 +1,3 @@
+-/* $OpenBSD: errno.h,v 1.20 2007/09/03 14:37:52 millert Exp $ */
+-/* $NetBSD: errno.h,v 1.10 1996/01/20 01:33:53 jtc Exp $ */
+-
+ /*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+@@ -37,6 +34,9 @@
+ * @(#)errno.h 8.5 (Berkeley) 1/21/94
+ */
+
++#ifndef _ERRNO_DEFS_H_
++#define _ERRNO_DEFS_H_
++
+ #define TARGET_EPERM 1 /* Operation not permitted */
+ #define TARGET_ENOENT 2 /* No such file or directory */
+ #define TARGET_ESRCH 3 /* No such process */
+@@ -147,3 +147,10 @@
+ #define TARGET_EIDRM 89 /* Identifier removed */
+ #define TARGET_ENOMSG 90 /* No message of desired type */
+ #define TARGET_ELAST 90 /* Must be equal largest errno */
++
++/* Internal errors: */
++#define TARGET_EJUSTRETURN 254 /* Just return without
++ modifing regs */
++#define TARGET_ERESTART 255 /* Restart syscall */
++
++#endif /* ! _ERRNO_DEFS_H_ */
+diff --git a/bsd-user/freebsd/host_os.h b/bsd-user/freebsd/host_os.h
+new file mode 100644
+index 0000000..efe2351
+--- /dev/null
++++ b/bsd-user/freebsd/host_os.h
+@@ -0,0 +1,46 @@
++/*
++ * FreeBSD host dependent code and definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __HOST_OS_H_
++#define __HOST_OS_H_
++
++#include <stdio.h>
++#include <sys/sysctl.h>
++
++#include "qemu.h"
++
++#define HOST_DEFAULT_BSD_TYPE target_freebsd
++
++static inline void save_proc_pathname(char *argv0)
++{
++ int mib[4];
++ size_t len;
++
++ mib[0] = CTL_KERN;
++ mib[1] = KERN_PROC;
++ mib[2] = KERN_PROC_PATHNAME;
++ mib[3] = -1;
++
++ len = PATH_MAX;
++ if (sysctl(mib, 4, qemu_proc_pathname, &len, NULL, 0)) {
++ perror("sysctl");
++ }
++}
++
++#endif /*!__HOST_OS_H_ */
+diff --git a/bsd-user/freebsd/os-extattr.c b/bsd-user/freebsd/os-extattr.c
+new file mode 100644
+index 0000000..95e7b24
+--- /dev/null
++++ b/bsd-user/freebsd/os-extattr.c
+@@ -0,0 +1,118 @@
++/*
++ * FreeBSD extend attributes and ACL conversions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#ifndef _ACL_PRIVATE
++#define _ACL_PRIVATE
++#endif
++#include <sys/acl.h>
++
++#include "qemu.h"
++#include "qemu-os.h"
++
++/*
++ * FreeBSD ACL conversion.
++ */
++abi_long t2h_freebsd_acl(struct acl *host_acl, abi_ulong target_addr)
++{
++ uint32_t i;
++ struct target_freebsd_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;
++}
++
++abi_long h2t_freebsd_acl(abi_ulong target_addr, struct acl *host_acl)
++{
++ uint32_t i;
++ struct target_freebsd_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);
++ __put_user(host_acl->acl_entry[i].ae_entry_type,
++ &target_acl->acl_entry[i].ae_entry_type);
++ __put_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;
++}
++
++abi_long t2h_freebsd_acl_type(acl_type_t *host_type, abi_long target_type)
++{
++
++ switch (target_type) {
++ case TARGET_FREEBSD_ACL_TYPE_ACCESS_OLD:
++ *host_type = ACL_TYPE_ACCESS_OLD;
++ break;
++
++ case TARGET_FREEBSD_ACL_TYPE_DEFAULT_OLD:
++ *host_type = ACL_TYPE_DEFAULT_OLD;
++ break;
++
++ case TARGET_FREEBSD_ACL_TYPE_ACCESS:
++ *host_type = ACL_TYPE_ACCESS;
++ break;
++
++ case TARGET_FREEBSD_ACL_TYPE_DEFAULT:
++ *host_type = ACL_TYPE_ACCESS;
++ break;
++
++ case TARGET_FREEBSD_ACL_TYPE_NFS4:
++ *host_type = ACL_TYPE_NFS4;
++ break;
++
++ default:
++ return -TARGET_EINVAL;
++ }
++ return 0;
++}
++
+diff --git a/bsd-user/freebsd/os-extattr.h b/bsd-user/freebsd/os-extattr.h
+new file mode 100644
+index 0000000..2e45f42
+--- /dev/null
++++ b/bsd-user/freebsd/os-extattr.h
+@@ -0,0 +1,654 @@
++/*
++ * FreeBSD extended attributes and ACL system call support
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/extattr.h>
++#ifndef _ACL_PRIVATE
++#define _ACL_PRIVATE
++#endif
++#include <sys/acl.h>
++
++#include "qemu-os.h"
++
++/* extattrctl() */
++static inline abi_long do_freebsd_extattrctl(abi_ulong arg1, abi_ulong arg2,
++ abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++ abi_long ret;
++ void *p, *a, *f;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ f = lock_user_string(arg3);
++ if (f == NULL) {
++ unlock_user(p, arg1, 0);
++ return -TARGET_EFAULT;
++ }
++ a = lock_user_string(arg5);
++ if (a == NULL) {
++ unlock_user(f, arg3, 0);
++ unlock_user(p, arg1, 0);
++ return -TARGET_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);
++
++ return ret;
++}
++
++/* extattr_set_file(2) */
++static inline abi_long do_freebsd_extattr_set_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++ abi_long ret;
++ void *p, *a, *d;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ a = lock_user_string(arg3);
++ if (a == NULL) {
++ unlock_user(p, arg1, 0);
++ return -TARGET_EFAULT;
++ }
++ d = lock_user(VERIFY_READ, arg4, arg5, 1);
++ if (d == NULL) {
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++ return -TARGET_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);
++
++ return ret;
++}
++
++/* extattr_get_file(2) */
++static inline abi_long do_freebsd_extattr_get_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++ abi_long ret;
++ void *p, *a, *d;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ a = lock_user_string(arg3);
++ if (a == NULL) {
++ unlock_user(p, arg1, 0);
++ return -TARGET_EFAULT;
++ }
++ if (arg4 && arg5 > 0) {
++ d = lock_user(VERIFY_WRITE, arg4, arg5, 0);
++ if (d == NULL) {
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++ return -TARGET_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);
++
++ return ret;
++}
++
++/* extattr_delete_file(2) */
++static inline abi_long do_freebsd_extattr_delete_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++ abi_long ret;
++ void *p, *a;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ a = lock_user_string(arg3);
++ if (a == NULL) {
++ unlock_user(p, arg1, 0);
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(extattr_delete_file(path(p), arg2, a));
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* extattr_set_fd(2) */
++static inline abi_long do_freebsd_extattr_set_fd(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++ abi_long ret;
++ void *a, *d;
++
++ a = lock_user_string(arg3);
++ if (a == NULL) {
++ return -TARGET_EFAULT;
++ }
++ d = lock_user(VERIFY_READ, arg4, arg5, 1);
++ if (d == NULL) {
++ unlock_user(a, arg3, 0);
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(extattr_set_fd(arg1, arg2, a, d, arg5));
++ unlock_user(d, arg4, arg5);
++ unlock_user(a, arg3, 0);
++
++ return ret;
++}
++
++/* extattr_get_fd(2) */
++static inline abi_long do_freebsd_extattr_get_fd(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++ abi_long ret;
++ void *a, *d;
++
++ a = lock_user_string(arg3);
++ if (a == NULL) {
++ return -TARGET_EFAULT;
++ }
++
++ if (arg4 && arg5 > 0) {
++ d = lock_user(VERIFY_WRITE, arg4, arg5, 0);
++ if (d == NULL) {
++ unlock_user(a, arg3, 0);
++ return -TARGET_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);
++
++ return ret;
++}
++
++/* extattr_delete_fd(2) */
++static inline abi_long do_freebsd_extattr_delete_fd(abi_long arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++ abi_long ret;
++ void *a;
++
++ a = lock_user_string(arg3);
++ if (a == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(extattr_delete_fd(arg1, arg2, a));
++ unlock_user(a, arg3, 0);
++
++ return ret;
++}
++
++/* extattr_get_link(2) */
++static inline abi_long do_freebsd_extattr_get_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++ abi_long ret;
++ void *p, *a, *d;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ a = lock_user_string(arg3);
++ if (a == NULL) {
++ unlock_user(p, arg1, 0);
++ return -TARGET_EFAULT;
++ }
++ if (arg4 && arg5 > 0) {
++ d = lock_user(VERIFY_WRITE, arg4, arg5, 0);
++ if (d == NULL) {
++ return -TARGET_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);
++
++ return ret;
++}
++
++/* extattr_set_link(2) */
++static inline abi_long do_freebsd_extattr_set_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++ abi_long ret;
++ void *p, *a, *d;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ a = lock_user_string(arg3);
++ if (a == NULL) {
++ unlock_user(p, arg1, 0);
++ return -TARGET_EFAULT;
++ }
++ d = lock_user(VERIFY_READ, arg4, arg5, 1);
++ if (d == NULL) {
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++ return -TARGET_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);
++
++ return ret;
++}
++
++/* extattr_delete_link(2) */
++static inline abi_long do_freebsd_extattr_delete_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++ abi_long ret;
++ void *p, *a;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ a = lock_user_string(arg3);
++ if (a == NULL) {
++ unlock_user(p, arg1, 0);
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(extattr_delete_link(path(p), arg2, a));
++ unlock_user(a, arg3, 0);
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* extattr_list_fd(2) */
++static inline abi_long do_freebsd_extattr_list_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3, abi_ulong arg4)
++{
++ abi_long ret;
++ void *d;
++
++ if (arg3 && arg4 > 0) {
++ d = lock_user(VERIFY_WRITE, arg3, arg4, 0);
++ if (d == NULL) {
++ return -TARGET_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));
++ }
++ return ret;
++}
++
++/* extattr_list_file(2) */
++static inline abi_long do_freebsd_extattr_list_file(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4)
++{
++ abi_long ret;
++ void *p, *d;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ if (arg3 && arg4 > 0) {
++ d = lock_user(VERIFY_WRITE, arg3, arg4, 0);
++ if (d == NULL) {
++ unlock_user(p, arg1, 0);
++ return -TARGET_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);
++
++ return ret;
++}
++
++/* extattr_list_link(2) */
++static inline abi_long do_freebsd_extattr_list_link(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4)
++{
++ abi_long ret;
++ void *p, *d;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ if (arg3 && arg4 > 0) {
++ d = lock_user(VERIFY_WRITE, arg3, arg4, 0);
++ if (d == NULL) {
++ unlock_user(p, arg1, 0);
++ return -TARGET_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);
++
++ return ret;
++}
++
++/*
++ * Access Control Lists
++ */
++
++/* __acl_aclcheck_fd(int filedes, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_aclcheck_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ struct acl host_acl;
++ acl_type_t type;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ ret = t2h_freebsd_acl(&host_acl, arg3);
++ if (!is_error(ret)) {
++ ret = get_errno(__acl_aclcheck_fd(arg1, type, &host_acl));
++ }
++
++ return ret;
++}
++
++/* __acl_aclcheck_file(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_aclcheck_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++ abi_long ret;
++ void *p;
++ struct acl host_acl;
++ acl_type_t type;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = t2h_freebsd_acl(&host_acl, arg3);
++ if (!is_error(ret)) {
++ ret = get_errno(__acl_aclcheck_file(path(p) , arg2, &host_acl));
++ }
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* __acl_aclcheck_link(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_aclcheck_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++ abi_long ret;
++ void *p;
++ struct acl host_acl;
++ acl_type_t type;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = t2h_freebsd_acl(&host_acl, arg3);
++ if (!is_error(ret)) {
++ ret = get_errno(__acl_aclcheck_link(path(p), type, &host_acl));
++ }
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* int __acl_delete_fd(int filedes, acl_type_t type); */
++static inline abi_long do_freebsd__acl_delete_fd(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ acl_type_t type;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ return get_errno(__acl_delete_fd(arg1, type));
++}
++
++/* int __acl_delete_file(const char *path, acl_type_t type); */
++static inline abi_long do_freebsd__acl_delete_file(abi_ulong arg1,
++ abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ acl_type_t type;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(__acl_delete_file(path(p), type));
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* int __acl_delete_link(const char *path, acl_type_t type); */
++static inline abi_long do_freebsd__acl_delete_link(abi_ulong arg1,
++ abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ acl_type_t type;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(__acl_delete_link(path(p), type));
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* int __acl_get_fd(int filedes, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_get_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ acl_type_t type;
++ struct acl host_acl;
++
++ bzero(&host_acl, sizeof(struct acl));
++ host_acl.acl_maxcnt = ACL_MAX_ENTRIES;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ ret = get_errno(__acl_get_fd(arg1, type, &host_acl));
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_acl(arg3, &host_acl);
++ }
++
++ return ret;
++}
++
++/* __acl_get_file(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_get_file(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ void *p;
++ acl_type_t type;
++ struct acl host_acl;
++
++ bzero(&host_acl, sizeof(struct acl));
++ host_acl.acl_maxcnt = ACL_MAX_ENTRIES;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(__acl_get_file(path(p), type, &host_acl));
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_acl(arg3, &host_acl);
++ }
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* int __acl_get_link(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_get_link(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ void *p;
++ acl_type_t type;
++ struct acl host_acl;
++
++ bzero(&host_acl, sizeof(struct acl));
++ host_acl.acl_maxcnt = ACL_MAX_ENTRIES;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(__acl_get_link(path(p), type, &host_acl));
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_acl(arg3, &host_acl);
++ }
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* int __acl_set_fd(int filedes, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_set_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ acl_type_t type;
++ struct acl host_acl;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ ret = t2h_freebsd_acl(&host_acl, arg3);
++ if (!is_error(ret)) {
++ ret = get_errno(__acl_set_fd(arg1, type, &host_acl));
++ }
++
++ return ret;
++}
++
++/* int __acl_set_file(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_set_file(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ void *p;
++ acl_type_t type;
++ struct acl host_acl;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = t2h_freebsd_acl(&host_acl, arg3);
++ if (!is_error(ret)) {
++ ret = get_errno(__acl_set_file(path(p), type, &host_acl));
++ }
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* int __acl_set_link(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_set_link(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ void *p;
++ acl_type_t type;
++ struct acl host_acl;
++
++ ret = t2h_freebsd_acl_type(&type, arg2);
++ if (is_error(ret)) {
++ return ret;
++ }
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = t2h_freebsd_acl(&host_acl, arg3);
++ if (!is_error(ret)) {
++ ret = get_errno(__acl_set_link(path(p), type, &host_acl));
++ }
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
+diff --git a/bsd-user/freebsd/os-ioctl-cmds.h b/bsd-user/freebsd/os-ioctl-cmds.h
+new file mode 100644
+index 0000000..85d3c41
+--- /dev/null
++++ b/bsd-user/freebsd/os-ioctl-cmds.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/os-ioctl-filio.h b/bsd-user/freebsd/os-ioctl-filio.h
+new file mode 100644
+index 0000000..7e1aae9
+--- /dev/null
++++ b/bsd-user/freebsd/os-ioctl-filio.h
+@@ -0,0 +1,45 @@
++/*
++ * FreeBSD filio definitions for ioctl(2) emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _IOCTL_FILIO_H_
++#define _IOCTL_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 /* !_IOCTL_FILIO_H_ */
+diff --git a/bsd-user/freebsd/os-ioctl-ioccom.h b/bsd-user/freebsd/os-ioctl-ioccom.h
+new file mode 100644
+index 0000000..fb9456f
+--- /dev/null
++++ b/bsd-user/freebsd/os-ioctl-ioccom.h
+@@ -0,0 +1,54 @@
++/*
++ * FreeBSD ioccom definitions for ioctl(2) emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _IOCTL_IOCCOM_H_
++#define _IOCTL_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 /* !_IOCTL_IOCCOM_H_ */
+diff --git a/bsd-user/freebsd/os-ioctl-ttycom.h b/bsd-user/freebsd/os-ioctl-ttycom.h
+new file mode 100644
+index 0000000..b60db25
+--- /dev/null
++++ b/bsd-user/freebsd/os-ioctl-ttycom.h
+@@ -0,0 +1,257 @@
++/*
++ * FreeBSD ttycom definitions for ioctl(2) emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _IOCTL_TTYCOM_H_
++#define _IOCTL_TTYCOM_H_
++
++#include "os-ioctl-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 /*! _IOCTL_TTYCOM_H_ */
+diff --git a/bsd-user/freebsd/os-ioctl-types.h b/bsd-user/freebsd/os-ioctl-types.h
+new file mode 100644
+index 0000000..60b9288
+--- /dev/null
++++ b/bsd-user/freebsd/os-ioctl-types.h
+@@ -0,0 +1,7 @@
++
++STRUCT_SPECIAL(termios)
++
++STRUCT(winsize, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
++
++STRUCT(fiodgname_arg, TYPE_INT, TYPE_PTRVOID)
++
+diff --git a/bsd-user/freebsd/os-misc.h b/bsd-user/freebsd/os-misc.h
+new file mode 100644
+index 0000000..07e60fe
+--- /dev/null
++++ b/bsd-user/freebsd/os-misc.h
+@@ -0,0 +1,442 @@
++/*
++ * miscellaneous FreeBSD system call shims
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef __OS_MISC_H_
++#define __OS_MISC_H_
++
++#include <sys/cpuset.h>
++#include <sched.h>
++
++/* sched_setparam(2) */
++static inline abi_long do_freebsd_sched_setparam(pid_t pid,
++ abi_ulong target_sp_addr)
++{
++ abi_long ret;
++ struct sched_param host_sp;
++
++ ret = get_user_s32(host_sp.sched_priority, target_sp_addr);
++ if (!is_error(ret)) {
++ ret = get_errno(sched_setparam(pid, &host_sp));
++ }
++ return ret;
++}
++
++/* sched_get_param(2) */
++static inline abi_long do_freebsd_sched_getparam(pid_t pid,
++ abi_ulong target_sp_addr)
++{
++ abi_long ret;
++ struct sched_param host_sp;
++
++ ret = get_errno(sched_getparam(pid, &host_sp));
++ if (!is_error(ret)) {
++ ret = put_user_s32(host_sp.sched_priority, target_sp_addr);
++ }
++ return ret;
++}
++
++/* sched_setscheduler(2) */
++static inline abi_long do_freebsd_sched_setscheduler(pid_t pid, int policy,
++ abi_ulong target_sp_addr)
++{
++ abi_long ret;
++ struct sched_param host_sp;
++
++ ret = get_user_s32(host_sp.sched_priority, target_sp_addr);
++ if (!is_error(ret)) {
++ ret = get_errno(sched_setscheduler(pid, policy, &host_sp));
++ }
++ return ret;
++}
++
++/* sched_getscheduler(2) */
++static inline abi_long do_freebsd_sched_getscheduler(pid_t pid)
++{
++
++ return get_errno(sched_getscheduler(pid));
++}
++
++/* sched_getscheduler(2) */
++static inline abi_long do_freebsd_sched_rr_get_interval(pid_t pid,
++ abi_ulong target_ts_addr)
++{
++ abi_long ret;
++ struct timespec host_ts;
++
++ ret = get_errno(sched_rr_get_interval(pid, &host_ts));
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_timespec(target_ts_addr, &host_ts);
++ }
++ return ret;
++}
++
++/* cpuset(2) */
++static inline abi_long do_freebsd_cpuset(abi_ulong target_cpuid)
++{
++ abi_long ret;
++ cpusetid_t setid;
++
++ ret = get_errno(cpuset(&setid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ return put_user_s32(setid, target_cpuid);
++}
++
++#define target_to_host_cpuset_which(hp, t) { \
++ (*hp) = t; \
++} while (0)
++
++#define target_to_host_cpuset_level(hp, t) { \
++ (*hp) = t; \
++} while (0)
++
++/* cpuset_setid(2) */
++static inline abi_long do_freebsd_cpuset_setid(void *cpu_env, abi_long arg1,
++ abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++ id_t id; /* 64-bit value */
++ cpusetid_t setid;
++ cpuwhich_t which;
++
++ target_to_host_cpuset_which(&which, arg1);
++#if TARGET_ABI_BITS == 32
++ /* See if we need to align the register pairs */
++ if (regpairs_aligned(cpu_env)) {
++ id = target_offset64(arg3, arg4);
++ setid = arg5;
++ } else {
++ id = target_offset64(arg2, arg3);
++ setid = arg4;
++ }
++#else
++ id = arg2;
++ setid = arg3;
++#endif
++ return get_errno(cpuset_setid(which, id, setid));
++}
++
++/* cpuset_getid(2) */
++static inline abi_long do_freebsd_cpuset_getid(abi_long arg1, abi_ulong arg2,
++ abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++ abi_long ret;
++ id_t id; /* 64-bit value */
++ cpusetid_t setid;
++ cpuwhich_t which;
++ cpulevel_t level;
++ abi_ulong target_setid;
++
++ target_to_host_cpuset_which(&which, arg1);
++ target_to_host_cpuset_level(&level, arg2);
++#if TARGET_ABI_BITS == 32
++ id = target_offset64(arg3, arg4);
++ target_setid = arg5;
++#else
++ id = arg3;
++ target_setid = arg4;
++#endif
++ ret = get_errno(cpuset_getid(level, which, id, &setid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ return put_user_s32(setid, target_setid);
++}
++
++/* cpuset_getaffinity(2) */
++static inline abi_long do_freebsd_cpuset_getaffinity(abi_long arg1,
++ abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5,
++ abi_ulong arg6)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset_getaffinity()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset_setaffinity(2) */
++static inline abi_long do_freebsd_cpuset_setaffinity(abi_long arg1,
++ abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5,
++ abi_ulong arg6)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset_setaffinity()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* modfnext(2) */
++static inline abi_long do_freebsd_modfnext(abi_long modid)
++{
++
++ qemu_log("qemu: Unsupported syscall modfnext()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* modfind(2) */
++static inline abi_long do_freebsd_modfind(abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall modfind()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldload(2) */
++static inline abi_long do_freebsd_kldload(abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall kldload()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldunload(2) */
++static inline abi_long do_freebsd_kldunload(abi_long fileid)
++{
++
++ qemu_log("qemu: Unsupported syscall kldunload()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldunloadf(2) */
++static inline abi_long do_freebsd_kldunloadf(abi_long fileid, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall kldunloadf()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldfind(2) */
++static inline abi_long do_freebsd_kldfind(abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall kldfind()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldnext(2) */
++static inline abi_long do_freebsd_kldnext(abi_long fileid)
++{
++
++ qemu_log("qemu: Unsupported syscall kldnext()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* kldstat(2) */
++static inline abi_long do_freebsd_kldstat(abi_long fileid,
++ abi_ulong target_stat)
++{
++
++ qemu_log("qemu: Unsupported syscall kldstat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldfirstmod(2) */
++static inline abi_long do_freebsd_kldfirstmod(abi_long fileid)
++{
++
++ qemu_log("qemu: Unsupported syscall kldfirstmod()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldsym(2) */
++static inline abi_long do_freebsd_kldsym(abi_long fileid, abi_long cmd,
++ abi_ulong target_data)
++{
++
++ qemu_log("qemu: Unsupported syscall kldsym()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * Resource limits (undocumented except for rctl(8) and rctl.conf(5) )
++ */
++/* rctl_get_racct() */
++static inline abi_long do_freebsd_rctl_get_racct(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_get_racct()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_get_rules() */
++static inline abi_long do_freebsd_rctl_get_rules(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_get_rules()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_add_rule() */
++static inline abi_long do_freebsd_rctl_add_rule(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_add_rule()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_remove_rule() */
++static inline abi_long do_freebsd_rctl_remove_rule(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_remove_rule()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_get_limits() */
++static inline abi_long do_freebsd_rctl_get_limits(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_get_limits()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * Kernel environment
++ */
++
++/* kenv(2) */
++static inline abi_long do_freebsd_kenv(abi_long what, abi_ulong target_name,
++ abi_ulong target_value, abi_long len)
++{
++
++ qemu_log("qemu: Unsupported syscall kenv()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/*
++ * Mandatory Access Control
++ */
++
++/* __mac_get_proc */
++static inline abi_long do_freebsd___mac_get_proc(abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_proc()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_proc */
++static inline abi_long do_freebsd___mac_set_proc(abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_proc()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* __mac_get_fd */
++static inline abi_long do_freebsd___mac_get_fd(abi_long fd,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_fd */
++static inline abi_long do_freebsd___mac_set_fd(abi_long fd,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_get_file */
++static inline abi_long do_freebsd___mac_get_file(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_file */
++static inline abi_long do_freebsd___mac_set_file(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_get_link */
++static inline abi_long do_freebsd___mac_get_link(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_link */
++static inline abi_long do_freebsd___mac_set_link(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* mac_syscall */
++static inline abi_long do_freebsd_mac_syscall(abi_ulong target_policy,
++ abi_long call, abi_ulong target_arg)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_syscall()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/*
++ * New posix calls
++ */
++/* posix_fallocate(2) */
++static inline abi_long do_freebsd_posix_fallocate(abi_long fd, abi_ulong offset,
++ abi_ulong len)
++{
++
++ qemu_log("qemu: Unsupported syscall posix_fallocate()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* posix_openpt(2) */
++static inline abi_long do_freebsd_posix_openpt(abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall posix_openpt()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* posix_fadvise(2) */
++static inline abi_long do_freebsd_posix_fadvise(abi_long fd, abi_ulong offset,
++ abi_ulong len, abi_long advise)
++{
++
++ qemu_log("qemu: Unsupported syscall posix_fadvise()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++#endif /* ! __OS_MISC_H_ */
+diff --git a/bsd-user/freebsd/os-proc.c b/bsd-user/freebsd/os-proc.c
+new file mode 100644
+index 0000000..05df37f
+--- /dev/null
++++ b/bsd-user/freebsd/os-proc.c
+@@ -0,0 +1,309 @@
++/*
++ * FreeBSD process related emulation code
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <sys/queue.h>
++#include <sys/sysctl.h>
++#include <sys/unistd.h>
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
++#include <libprocstat.h>
++#endif
++#include <string.h>
++
++#include "qemu.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)
++{
++ char *ret = NULL;
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
++ unsigned int cnt;
++ struct procstat *procstat = NULL;
++ struct kinfo_proc *kipp = NULL;
++ struct filestat_list *head = NULL;
++ struct filestat *fst;
++
++ 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);
++ }
++#endif
++ return ret;
++}
++
++static int
++is_target_shell_script(int fd, char *interp, size_t size)
++{
++ char buf[2], *p, *b;
++ ssize_t n;
++
++ if (fd < 0) {
++ return 0;
++ }
++ (void)lseek(fd, 0L, SEEK_SET);
++ if (read(fd, buf, 2) != 2) {
++ return 0;
++ }
++ if (buf[0] != '#' && buf[1] != '!') {
++ return 0;
++ }
++ if (size == 0) {
++ return 0;
++ }
++ b = interp;
++ /* Remove the trailing whitespace after "#!", if any. */
++ while (size != 0) {
++ n = read(fd, b, 1);
++ if (n < 0 || n == 0) {
++ return 0;
++ }
++ if ((*b != ' ') && (*b != '\t')) {
++ b++;
++ size--;
++ break;
++ }
++ }
++ while (size != 0) {
++ n = read(fd, b, size);
++ if (n < 0 || n == 0) {
++ return 0;
++ }
++ if ((p = memchr(b, '\n', size)) != NULL) {
++ *p = 0;
++ return 1;
++ }
++ b += n;
++ size -= n;
++ }
++
++ return 0;
++}
++
++/*
++ * execve/fexecve
++ */
++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, **qarg0;
++ 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++;
++ }
++
++ qarg0 = argp = alloca((argc + 4) * sizeof(void *));
++ /* save the first agrument for the emulator */
++ *argp++ = (char *)getprogname();
++ qargp = argp;
++ *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;
++ }
++ *q = lock_user_string(addr);
++ if (*q == NULL) {
++ 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;
++ }
++ *q = lock_user_string(addr);
++ if (*q == NULL) {
++ 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) {
++ char execpath[PATH_MAX];
++
++ 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 if (is_target_shell_script((int)path_or_fd, execpath,
++ sizeof(execpath)) != 0) {
++ char scriptpath[PATH_MAX];
++
++ /* execve() as a target script using emulator. */
++ if (get_filename_from_fd(getpid(), (int)path_or_fd, scriptpath,
++ sizeof(scriptpath)) != NULL) {
++ *qargp = execpath;
++ *qarg1 = scriptpath;
++ ret = get_errno(execve(qemu_proc_pathname, qarg0, envp));
++ } else {
++ ret = -TARGET_EBADF;
++ goto execve_end;
++ }
++ } else {
++ ret = get_errno(fexecve((int)path_or_fd, argp, envp));
++ }
++ } else {
++ int fd;
++ char execpath[PATH_MAX];
++
++ p = lock_user_string(path_or_fd);
++ if (p == NULL) {
++ 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 if (is_target_shell_script(fd, execpath,
++ sizeof(execpath)) != 0) {
++ close(fd);
++ /* execve() as a target script using emulator. */
++ *qargp = execpath;
++ *qarg1 = (char *)p;
++ ret = get_errno(execve(qemu_proc_pathname, qarg0, 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;
++}
++
++
+diff --git a/bsd-user/freebsd/os-proc.h b/bsd-user/freebsd/os-proc.h
+new file mode 100644
+index 0000000..b31f7c4
+--- /dev/null
++++ b/bsd-user/freebsd/os-proc.h
+@@ -0,0 +1,428 @@
++/*
++ * process related system call shims and definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __FREEBSD_PROC_H_
++#define __FREEBSD_PROC_H_
++
++#include <sys/types.h>
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
++#include <sys/procdesc.h>
++#endif
++#include <sys/wait.h>
++#include <unistd.h>
++
++#include "target_arch_cpu.h"
++
++extern int __setugid(int flag);
++extern int pdwait4(int fd, int *status, int options, struct rusage *rusage);
++
++/* execve(2) */
++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);
++}
++
++/* fexecve(2) */
++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);
++}
++
++/* wait4(2) */
++static inline abi_long do_freebsd_wait4(abi_long arg1, abi_ulong target_status,
++ abi_long arg3, abi_ulong target_rusage)
++{
++ abi_long ret;
++ int status;
++ struct rusage rusage, *rusage_ptr = NULL;
++
++ if (target_rusage) {
++ rusage_ptr = &rusage;
++ }
++ ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
++ if (!is_error(ret)) {
++ status = host_to_target_waitstatus(status);
++ if (put_user_s32(status, target_status) != 0) {
++ return -TARGET_EFAULT;
++ }
++ if (target_rusage != 0) {
++ host_to_target_rusage(target_rusage, &rusage);
++ }
++ }
++ return ret;
++}
++
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
++/* setloginclass(2) */
++static inline abi_long do_freebsd_setloginclass(abi_ulong arg1)
++{
++ abi_long ret;
++ void *p;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(setloginclass(p));
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* getloginclass(2) */
++static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2)
++{
++ abi_long ret;
++ void *p;
++
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(getloginclass(p, arg2));
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* pdwait4(2) */
++static inline abi_long do_freebsd_pdwait4(abi_long arg1,
++ abi_ulong target_status, abi_long arg3, abi_ulong target_rusage)
++{
++ abi_long ret;
++ int status;
++ struct rusage rusage, *rusage_ptr = NULL;
++
++ if (target_rusage) {
++ rusage_ptr = &rusage;
++ }
++ ret = get_errno(pdwait4(arg1, &status, arg3, rusage_ptr));
++ if (!is_error(ret)) {
++ status = host_to_target_waitstatus(status);
++ if (put_user_s32(status, target_status) != 0) {
++ return -TARGET_EFAULT;
++ }
++ if (target_rusage != 0) {
++ host_to_target_rusage(target_rusage, &rusage);
++ }
++ }
++ return ret;
++}
++
++/* pdgetpid(2) */
++static inline abi_long do_freebsd_pdgetpid(abi_long fd, abi_ulong target_pidp)
++{
++ abi_long ret;
++ pid_t pid;
++
++ ret = get_errno(pdgetpid(fd, &pid));
++ if (!is_error(ret)) {
++ if (put_user_u32(pid, target_pidp)) {
++ return -TARGET_EFAULT;
++ }
++ }
++ return ret;
++}
++
++#else
++
++/* setloginclass(2) */
++static inline abi_long do_freebsd_setloginclass(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall setloginclass()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getloginclass(2) */
++static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall getloginclass()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* pdwait4(2) */
++static inline abi_long do_freebsd_pdwait4(abi_long arg1,
++ abi_ulong target_status, abi_long arg3, abi_ulong target_rusage)
++{
++
++ qemu_log("qemu: Unsupported syscall pdwait4()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* pdgetpid(2) */
++static inline abi_long do_freebsd_pdgetpid(abi_long fd, abi_ulong target_pidp)
++{
++
++ qemu_log("qemu: Unsupported syscall pdgetpid()\n");
++ return -TARGET_ENOSYS;
++}
++#endif /* ! __FreeBSD_version > 900000 */
++
++/* undocumented __setugid */
++static inline abi_long do_freebsd___setugid(abi_long arg1)
++{
++
++ return get_errno(__setugid(arg1));
++}
++
++/* fork(2) */
++static inline abi_long do_freebsd_fork(void *cpu_env)
++{
++ abi_long ret;
++ abi_ulong child_flag = 0;
++
++ fork_start();
++ ret = fork();
++ if (ret == 0) {
++ /* child */
++ child_flag = 1;
++ target_cpu_clone_regs(cpu_env, 0);
++ } else {
++ /* parent */
++ fork_end(0);
++ }
++
++ /*
++ * The fork system call sets a child flag in the second return
++ * value: 0 for parent process, 1 for child process.
++ */
++ set_second_rval(cpu_env, child_flag);
++
++ return ret;
++}
++
++/* vfork(2) */
++static inline abi_long do_freebsd_vfork(void *cpu_env)
++{
++
++ return do_freebsd_fork(cpu_env);
++}
++
++/* rfork(2) */
++static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags)
++{
++ abi_long ret;
++ abi_ulong child_flag = 0;
++
++ fork_start();
++ ret = rfork(flags);
++ if (ret == 0) {
++ /* child */
++ child_flag = 1;
++ target_cpu_clone_regs(cpu_env, 0);
++ } else {
++ /* parent */
++ fork_end(0);
++ }
++
++ /*
++ * The fork system call sets a child flag in the second return
++ * value: 0 for parent process, 1 for child process.
++ */
++ set_second_rval(cpu_env, child_flag);
++
++ return ret;
++
++}
++
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
++/* pdfork(2) */
++static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong target_fdp,
++ abi_long flags)
++{
++ abi_long ret;
++ abi_ulong child_flag = 0;
++ int fd;
++
++ fork_start();
++ ret = pdfork(&fd, flags);
++ if (ret == 0) {
++ /* child */
++ child_flag = 1;
++ target_cpu_clone_regs(cpu_env, 0);
++ } else {
++ /* parent */
++ fork_end(0);
++ }
++ if (put_user_s32(fd, target_fdp)) {
++ return -TARGET_EFAULT;
++ }
++
++ /*
++ * The fork system call sets a child flag in the second return
++ * value: 0 for parent process, 1 for child process.
++ */
++ set_second_rval(cpu_env, child_flag);
++
++ return ret;
++}
++
++#else
++
++/* pdfork(2) */
++static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong arg1,
++ abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall pdfork()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* __FreeBSD_version > 900000 */
++
++/* jail(2) */
++static inline abi_long do_freebsd_jail(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall jail()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_attach(2) */
++static inline abi_long do_freebsd_jail_attach(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_attach()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_remove(2) */
++static inline abi_long do_freebsd_jail_remove(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_remove()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_get(2) */
++static inline abi_long do_freebsd_jail_get(abi_ulong arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_get()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_set(2) */
++static inline abi_long do_freebsd_jail_set(abi_ulong arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_set()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_enter(2) */
++static inline abi_long do_freebsd_cap_enter(void)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_enter()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_new(2) */
++static inline abi_long do_freebsd_cap_new(abi_long arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_new()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_getrights(2) */
++static inline abi_long do_freebsd_cap_getrights(abi_long arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_getrights()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_getmode(2) */
++static inline abi_long do_freebsd_cap_getmode(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_getmode()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* audit(2) */
++static inline abi_long do_freebsd_audit(abi_ulong arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall audit()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* auditon(2) */
++static inline abi_long do_freebsd_auditon(abi_long arg1, abi_ulong arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall auditon()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getaudit(2) */
++static inline abi_long do_freebsd_getaudit(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall getaudit()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setaudit(2) */
++static inline abi_long do_freebsd_setaudit(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall setaudit()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getaudit_addr(2) */
++static inline abi_long do_freebsd_getaudit_addr(abi_ulong arg1,
++ abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall getaudit_addr()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setaudit_addr(2) */
++static inline abi_long do_freebsd_setaudit_addr(abi_ulong arg1,
++ abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall setaudit_addr()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* auditctl(2) */
++static inline abi_long do_freebsd_auditctl(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall auditctl()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* ! __FREEBSD_PROC_H_ */
+diff --git a/bsd-user/freebsd/os-signal.h b/bsd-user/freebsd/os-signal.h
+new file mode 100644
+index 0000000..d4a26da
+--- /dev/null
++++ b/bsd-user/freebsd/os-signal.h
+@@ -0,0 +1,43 @@
++/*
++ * FreeBSD signal system call shims
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __FREEBSD_OS_SIGNAL_H_
++#define __FREEBSD_OS_SIGNAL_H_
++
++#include <sys/procdesc.h>
++
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
++/* pdkill(2) */
++static inline abi_long do_freebsd_pdkill(abi_long arg1, abi_long arg2)
++{
++
++ return get_errno(pdkill(arg1, arg2));
++}
++
++#else
++
++static inline abi_long do_freebsd_pdkill(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall pdkill()\n");
++ return -TARGET_ENOSYS;
++}
++#endif /* ! __FreeBSD_version > 900000 */
++
++#endif /* ! __FREEBSD_OS_SIGNAL_H_ */
+diff --git a/bsd-user/freebsd/os-socket.c b/bsd-user/freebsd/os-socket.c
+new file mode 100644
+index 0000000..949af28
+--- /dev/null
++++ b/bsd-user/freebsd/os-socket.c
+@@ -0,0 +1,149 @@
++/*
++ * FreeBSD socket related system call helpers
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++
++#include "qemu.h"
++#include "qemu-os.h"
++
++abi_long t2h_freebsd_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 == 0) {
++ 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;
++}
++
++abi_long h2t_freebsd_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 == 0) {
++ 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_freebsd_timeval *target_tv =
++ (struct target_freebsd_timeval *)target_data;
++ __put_user(tv->tv_sec, &target_tv->tv_sec);
++ __put_user(tv->tv_usec, &target_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;
++}
++
+diff --git a/bsd-user/freebsd/os-socket.h b/bsd-user/freebsd/os-socket.h
+new file mode 100644
+index 0000000..9339ffb
+--- /dev/null
++++ b/bsd-user/freebsd/os-socket.h
+@@ -0,0 +1,548 @@
++/*
++ * FreeBSD socket related system call shims
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef __FREEBSD_SOCKET_H_
++#define __FREEBSD_SOCKET_H_
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <netinet/in.h>
++
++#include "qemu-os.h"
++
++/* sendmsg(2) */
++static inline abi_long do_freebsd_sendmsg(int fd, abi_ulong target_msg,
++ int flags)
++{
++ abi_long ret;
++ struct target_msghdr *msgp;
++ struct msghdr msg;
++ int count;
++ struct iovec *vec;
++ abi_ulong target_vec;
++
++ if (!lock_user_struct(VERIFY_READ, msgp, target_msg, 1)) {
++ 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 (is_error(ret)) {
++ unlock_user_struct(msgp, target_msg, 0);
++ 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(VERIFY_READ, vec, target_vec, count, 1);
++ msg.msg_iovlen = count;
++ msg.msg_iov = vec;
++
++ ret = t2h_freebsd_cmsg(&msg, msgp);
++ if (!is_error(ret)) {
++ ret = get_errno(sendmsg(fd, &msg, flags));
++ }
++ unlock_iovec(vec, target_vec, count, 0);
++ unlock_user_struct(msgp, target_msg, 0);
++ return ret;
++}
++
++/* recvmsg(2) */
++static inline abi_long do_freebsd_recvmsg(int fd, abi_ulong target_msg,
++ int flags)
++{
++ abi_long ret, len;
++ struct target_msghdr *msgp;
++ struct msghdr msg;
++ int count;
++ struct iovec *vec;
++ abi_ulong target_vec;
++
++ if (!lock_user_struct(VERIFY_WRITE, msgp, target_msg, 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 (is_error(ret)) {
++ unlock_user_struct(msgp, target_msg, 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(VERIFY_WRITE, vec, target_vec, count, 0);
++ msg.msg_iovlen = count;
++ msg.msg_iov = vec;
++
++ ret = get_errno(recvmsg(fd, &msg, flags));
++ if (!is_error(ret)) {
++ len = ret;
++ ret = h2t_freebsd_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 (is_error(ret)) {
++ goto out;
++ }
++ }
++ }
++ ret = len;
++ }
++out:
++ unlock_iovec(vec, target_vec, count, 1);
++ unlock_user_struct(msgp, target_msg, 1);
++ return ret;
++}
++
++/* setsockopt(2) */
++static inline abi_long do_bsd_setsockopt(int sockfd, int level, int optname,
++ abi_ulong optval_addr, socklen_t optlen)
++{
++ 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. */
++ 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;
++
++#ifdef SO_USER_COOKIE
++ case TARGET_SO_USER_COOKIE:
++ optname = SO_USER_COOKIE;
++ break;
++#endif
++ 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;
++}
++
++/* getsockopt(2) */
++static inline abi_long do_bsd_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;
++
++ 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:
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000 && defined(IP_RECVTOS)
++ case IP_RECVTOS:
++#endif
++ 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;
++ break;
++ }
++ return ret;
++}
++
++/* setfib(2) */
++static inline abi_long do_freebsd_setfib(abi_long fib)
++{
++
++ return get_errno(setfib(fib));
++}
++
++/* sctp_peeloff(2) */
++static inline abi_long do_freebsd_sctp_peeloff(abi_long s, abi_ulong id)
++{
++
++ qemu_log("qemu: Unsupported syscall sctp_peeloff()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sctp_generic_sendmsg(2) */
++static inline abi_long do_freebsd_sctp_generic_sendmsg(abi_long s,
++ abi_ulong target_msg, abi_long msglen, abi_ulong target_to,
++ abi_ulong len, abi_ulong target_sinfo, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall sctp_generic_sendmsg()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sctp_generic_recvmsg(2) */
++static inline abi_long do_freebsd_sctp_generic_recvmsg(abi_long s,
++ abi_ulong target_iov, abi_long iovlen, abi_ulong target_from,
++ abi_ulong fromlen, abi_ulong target_sinfo, abi_ulong target_msgflags)
++{
++
++ qemu_log("qemu: Unsupported syscall sctp_generic_recvmsg()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* freebsd4_sendfile(2) */
++static inline abi_long do_freebsd_freebsd4_sendfile(abi_long fd, abi_long s,
++ abi_ulong arg3, abi_ulong arg4, abi_ulong nbytes, abi_ulong target_hdtr,
++ abi_ulong target_sbytes, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall freebsd4_sendfile()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sendfile(2) */
++static inline abi_long do_freebsd_sendfile(abi_long fd, abi_long s,
++ abi_ulong arg3, abi_ulong arg4, abi_ulong nbytes, abi_ulong target_hdtr,
++ abi_ulong target_sbytes, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall sendfile()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* !__FREEBSD_SOCKET_H_ */
+diff --git a/bsd-user/freebsd/os-stat.c b/bsd-user/freebsd/os-stat.c
+new file mode 100644
+index 0000000..50885d1
+--- /dev/null
++++ b/bsd-user/freebsd/os-stat.c
+@@ -0,0 +1,234 @@
++/*
++ * FreeBSD stat related conversion routines
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/mount.h>
++
++#include "qemu.h"
++#include "qemu-os.h"
++
++/*
++ * stat conversion
++ */
++abi_long h2t_freebsd_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;
++}
++
++abi_long h2t_freebsd_nstat(abi_ulong target_addr, struct stat *host_st)
++{
++ struct target_freebsd_nstat *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);
++ __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;
++}
++
++/*
++ * file handle conversion
++ */
++abi_long t2h_freebsd_fhandle(fhandle_t *host_fh, abi_ulong target_addr)
++{
++ target_freebsd_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;
++}
++
++abi_long h2t_freebsd_fhandle(abi_ulong target_addr, fhandle_t *host_fh)
++{
++ target_freebsd_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;
++}
++
++/*
++ * file system stat
++ */
++abi_long h2t_freebsd_statfs(abi_ulong target_addr, struct statfs *host_statfs)
++{
++ struct target_freebsd_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;
++}
++
++/*
++ * fcntl cmd conversion
++ */
++abi_long 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;
++
++#ifdef F_DUPFD_CLOEXEC
++ case TARGET_F_DUPFD_CLOEXEC:
++ return F_DUPFD_CLOEXEC;
++#endif
++
++#ifdef F_DUP2FD_CLOEXEC
++ case TARGET_F_DUP2FD_CLOEXEC:
++ return F_DUP2FD_CLOEXEC;
++#endif
++
++ default:
++ return -TARGET_EINVAL;
++ }
++}
++
+diff --git a/bsd-user/freebsd/os-stat.h b/bsd-user/freebsd/os-stat.h
+new file mode 100644
+index 0000000..ed6bcab
+--- /dev/null
++++ b/bsd-user/freebsd/os-stat.h
+@@ -0,0 +1,437 @@
++/*
++ * stat related system call shims and definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __FREEBSD_STAT_H_
++#define __FREEBSD_STAT_H_
++
++#include <sys/types.h>
++#include <sys/ucred.h>
++#include <sys/mount.h>
++#include <sys/stat.h>
++#include <dirent.h>
++
++#include "qemu-os.h"
++
++/* undocumented nstat system calls */
++int nstat(const char *path, struct stat *sb);
++int nlstat(const char *path, struct stat *sb);
++int nfstat(int fd, struct stat *sb);
++
++/* stat(2) */
++static inline abi_long do_freebsd_stat(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ struct stat st;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(stat(path(p), &st));
++ UNLOCK_PATH(p, arg1);
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_stat(arg2, &st);
++ }
++ return ret;
++}
++
++/* lstat(2) */
++static inline abi_long do_freebsd_lstat(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ struct stat st;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(lstat(path(p), &st));
++ UNLOCK_PATH(p, arg1);
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_stat(arg2, &st);
++ }
++ return ret;
++}
++
++/* fstat(2) */
++static inline abi_long do_freebsd_fstat(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ struct stat st;
++
++ ret = get_errno(fstat(arg1, &st));
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_stat(arg2, &st);
++ }
++ return ret;
++}
++
++/* fstatat(2) */
++static inline abi_long do_freebsd_fstatat(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++ abi_long ret;
++ void *p;
++ struct stat st;
++
++ LOCK_PATH(p, arg2);
++ ret = get_errno(fstatat(arg1, p, &st, arg4));
++ UNLOCK_PATH(p, arg2);
++ if (!is_error(ret) && arg3) {
++ ret = h2t_freebsd_stat(arg3, &st);
++ }
++ return ret;
++}
++
++/* undocummented nstat(char *path, struct nstat *ub) syscall */
++static abi_long do_freebsd_nstat(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ struct stat st;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(nstat(path(p), &st));
++ UNLOCK_PATH(p, arg1);
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_nstat(arg2, &st);
++ }
++ return ret;
++}
++
++/* undocummented nfstat(int fd, struct nstat *sb) syscall */
++static abi_long do_freebsd_nfstat(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ struct stat st;
++
++ ret = get_errno(nfstat(arg1, &st));
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_nstat(arg2, &st);
++ }
++ return ret;
++}
++
++/* undocummented nlstat(char *path, struct nstat *ub) syscall */
++static abi_long do_freebsd_nlstat(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ struct stat st;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(nlstat(path(p), &st));
++ UNLOCK_PATH(p, arg1);
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_nstat(arg2, &st);
++ }
++ return ret;
++}
++
++/* getfh(2) */
++static abi_long do_freebsd_getfh(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ fhandle_t host_fh;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(getfh(path(p), &host_fh));
++ UNLOCK_PATH(p, arg1);
++ if (is_error(ret)) {
++ return ret;
++ }
++ return h2t_freebsd_fhandle(arg2, &host_fh);
++}
++
++/* lgetfh(2) */
++static inline abi_long do_freebsd_lgetfh(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ fhandle_t host_fh;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(lgetfh(path(p), &host_fh));
++ UNLOCK_PATH(p, arg1);
++ if (is_error(ret)) {
++ return ret;
++ }
++ return h2t_freebsd_fhandle(arg2, &host_fh);
++}
++
++/* fhopen(2) */
++static inline abi_long do_freebsd_fhopen(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ fhandle_t host_fh;
++
++ ret = t2h_freebsd_fhandle(&host_fh, arg1);
++ if (is_error(ret)) {
++ return ret;
++ }
++
++ return get_errno(fhopen(&host_fh, arg2));
++}
++
++/* fhstat(2) */
++static inline abi_long do_freebsd_fhstat(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ fhandle_t host_fh;
++ struct stat host_sb;
++
++ ret = t2h_freebsd_fhandle(&host_fh, arg1);
++ if (is_error(ret)) {
++ return ret;
++ }
++ ret = get_errno(fhstat(&host_fh, &host_sb));
++ if (is_error(ret)) {
++ return ret;
++ }
++ return h2t_freebsd_stat(arg2, &host_sb);
++}
++
++/* fhstatfs(2) */
++static inline abi_long do_freebsd_fhstatfs(abi_ulong target_fhp_addr,
++ abi_ulong target_stfs_addr)
++{
++ abi_long ret;
++ fhandle_t host_fh;
++ struct statfs host_stfs;
++
++ ret = t2h_freebsd_fhandle(&host_fh, target_fhp_addr);
++ if (is_error(ret)) {
++ return ret;
++ }
++ ret = get_errno(fhstatfs(&host_fh, &host_stfs));
++ if (is_error(ret)) {
++ return ret;
++ }
++ return h2t_freebsd_statfs(target_stfs_addr, &host_stfs);
++}
++
++/* statfs(2) */
++static inline abi_long do_freebsd_statfs(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ struct statfs host_stfs;
++
++ LOCK_PATH(p, arg1);
++ ret = get_errno(statfs(path(p), &host_stfs));
++ UNLOCK_PATH(p, arg1);
++ if (is_error(ret)) {
++ return ret;
++ }
++
++ return h2t_freebsd_statfs(arg2, &host_stfs);
++}
++
++/* fstatfs(2) */
++static inline abi_long do_freebsd_fstatfs(abi_long fd, abi_ulong target_addr)
++{
++ abi_long ret;
++ struct statfs host_stfs;
++
++ ret = get_errno(fstatfs(fd, &host_stfs));
++ if (is_error(ret)) {
++ return ret;
++ }
++
++ return h2t_freebsd_statfs(target_addr, &host_stfs);
++}
++
++/* getfsstat(2) */
++static inline abi_long do_freebsd_getfsstat(abi_ulong target_addr,
++ abi_long bufsize, abi_long flags)
++{
++ abi_long ret;
++ struct statfs *host_stfs;
++ int count;
++ long host_bufsize;
++
++ count = bufsize / sizeof(struct target_freebsd_statfs);
++
++ /* if user buffer is NULL then return number of mounted FS's */
++ if (target_addr == 0 || count == 0) {
++ 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 (is_error(ret)) {
++ return ret;
++ }
++
++ while (count--) {
++ if (h2t_freebsd_statfs((target_addr +
++ (count * sizeof(struct target_freebsd_statfs))),
++ &host_stfs[count])) {
++ return -TARGET_EFAULT;
++ }
++ }
++ return ret;
++}
++
++/* getdents(2) */
++static inline abi_long do_freebsd_getdents(abi_long arg1, abi_ulong arg2,
++ abi_long nbytes)
++{
++ abi_long ret;
++ struct dirent *dirp;
++
++ dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
++ if (dirp == NULL) {
++ return -TARGET_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) {
++ return -TARGET_EFAULT;
++ }
++ de->d_reclen = tswap16(reclen);
++ de->d_fileno = tswap32(de->d_fileno);
++ len -= reclen;
++ }
++ }
++ return ret;
++}
++
++/* getdirecentries(2) */
++static inline abi_long do_freebsd_getdirentries(abi_long arg1, abi_ulong arg2,
++ abi_long nbytes, abi_ulong arg4)
++{
++ abi_long ret;
++ struct dirent *dirp;
++ long basep;
++
++ dirp = lock_user(VERIFY_WRITE, arg2, nbytes, 0);
++ if (dirp == NULL) {
++ return -TARGET_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) {
++ return -TARGET_EFAULT;
++ }
++ 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(basep, arg4, abi_ulong)) {
++ return -TARGET_EFAULT;
++ }
++ }
++ return ret;
++}
++
++/* fcntl(2) */
++static inline abi_long do_freebsd_fcntl(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ int host_cmd;
++ struct flock fl;
++ struct target_freebsd_flock *target_fl;
++
++ host_cmd = target_to_host_fcntl_cmd(arg2);
++ if (host_cmd < 0) {
++ return host_cmd;
++ }
++ switch (arg2) {
++ case TARGET_F_GETLK:
++ if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) {
++ return -TARGET_EFAULT;
++ }
++ __get_user(fl.l_type, &target_fl->l_type);
++ __get_user(fl.l_whence, &target_fl->l_whence);
++ __get_user(fl.l_start, &target_fl->l_start);
++ __get_user(fl.l_len, &target_fl->l_len);
++ __get_user(fl.l_pid, &target_fl->l_pid);
++ __get_user(fl.l_sysid, &target_fl->l_sysid);
++ unlock_user_struct(target_fl, arg3, 0);
++ ret = get_errno(fcntl(arg1, host_cmd, &fl));
++ if (!is_error(ret)) {
++ if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0)) {
++ return -TARGET_EFAULT;
++ }
++ __put_user(fl.l_type, &target_fl->l_type);
++ __put_user(fl.l_whence, &target_fl->l_whence);
++ __put_user(fl.l_start, &target_fl->l_start);
++ __put_user(fl.l_len, &target_fl->l_len);
++ __put_user(fl.l_pid, &target_fl->l_pid);
++ __put_user(fl.l_sysid, &target_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;
++ }
++ __get_user(fl.l_type, &target_fl->l_type);
++ __get_user(fl.l_whence, &target_fl->l_whence);
++ __get_user(fl.l_start, &target_fl->l_start);
++ __get_user(fl.l_len, &target_fl->l_len);
++ __get_user(fl.l_pid, &target_fl->l_pid);
++ __get_user(fl.l_sysid, &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;
++ }
++ return ret;
++}
++
++#endif /* ! __FREEBSD_STAT_H_ */
+diff --git a/bsd-user/freebsd/os-strace.h b/bsd-user/freebsd/os-strace.h
+new file mode 100644
+index 0000000..a222f09
+--- /dev/null
++++ b/bsd-user/freebsd/os-strace.h
+@@ -0,0 +1,29 @@
++/*
++ * FreeBSD dependent strace print functions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include "target_arch_sysarch.h" /* architecture dependent functions */
++
++
++static inline void do_os_print_sysarch(const struct syscallname *name,
++ abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4,
++ abi_long arg5, abi_long arg6)
++{
++ /* This is arch dependent */
++ do_freebsd_arch_print_sysarch(name, arg1, arg2, arg3, arg4, arg5, arg6);
++}
+diff --git a/bsd-user/freebsd/os-sys.c b/bsd-user/freebsd/os-sys.c
+new file mode 100644
+index 0000000..c8f999f
+--- /dev/null
++++ b/bsd-user/freebsd/os-sys.c
+@@ -0,0 +1,284 @@
++/*
++ * FreeBSD sysctl() and sysarch() system call emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <sys/param.h>
++#include <sys/sysctl.h>
++#include <string.h>
++
++#include "qemu.h"
++
++#include "target_arch_sysarch.h"
++#include "target_os_vmparam.h"
++
++/*
++ * XXX this uses the undocumented oidfmt interface to find the kind of
++ * a requested sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt()
++ * (compare to src/sbin/sysctl/sysctl.c)
++ */
++static int
++oidfmt(int *oid, int len, char *fmt, uint32_t *kind)
++{
++ int qoid[CTL_MAXNAME+2];
++ uint8_t buf[BUFSIZ];
++ int i;
++ size_t j;
++
++ qoid[0] = 0;
++ qoid[1] = 4;
++ memcpy(qoid + 2, oid, len * sizeof(int));
++
++ j = sizeof(buf);
++ i = sysctl(qoid, len + 2, buf, &j, 0, 0);
++ if (i) {
++ return i;
++ }
++
++ if (kind) {
++ *kind = *(uint32_t *)buf;
++ }
++
++ if (fmt) {
++ strcpy(fmt, (char *)(buf + sizeof(uint32_t)));
++ }
++ return 0;
++}
++
++/*
++ * try and convert sysctl return data for the target.
++ * XXX doesn't handle CTLTYPE_OPAQUE and CTLTYPE_STRUCT.
++ */
++static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind)
++{
++ switch (kind & CTLTYPE) {
++ case CTLTYPE_INT:
++ case CTLTYPE_UINT:
++ *(uint32_t *)holdp = tswap32(*(uint32_t *)holdp);
++ break;
++
++#ifdef TARGET_ABI32
++ case CTLTYPE_LONG:
++ case CTLTYPE_ULONG:
++ *(uint32_t *)holdp = tswap32(*(long *)holdp);
++ break;
++#else
++ case CTLTYPE_LONG:
++ *(uint64_t *)holdp = tswap64(*(long *)holdp);
++ case CTLTYPE_ULONG:
++ *(uint64_t *)holdp = tswap64(*(unsigned long *)holdp);
++ break;
++#endif
++#if !defined(__FreeBSD_version) || __FreeBSD_version < 900031
++ case CTLTYPE_QUAD:
++#else
++ case CTLTYPE_U64:
++ case CTLTYPE_S64:
++#endif
++ *(uint64_t *)holdp = tswap64(*(uint64_t *)holdp);
++ break;
++
++ case CTLTYPE_STRING:
++ break;
++
++ default:
++ /* XXX unhandled */
++ return -1;
++ }
++ 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]);
++}
++
++abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen,
++ abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen)
++{
++ abi_long ret;
++ 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;
++ TaskState *ts = (TaskState *)env->opaque;
++
++ if (oldlenp) {
++ if (get_user_ual(oldlen, oldlenp)) {
++ return -TARGET_EFAULT;
++ }
++ }
++ hnamep = lock_user(VERIFY_READ, namep, namelen, 1);
++ if (hnamep == NULL) {
++ return -TARGET_EFAULT;
++ }
++ if (newp) {
++ hnewp = lock_user(VERIFY_READ, newp, newlen, 1);
++ if (hnewp == NULL) {
++ return -TARGET_EFAULT;
++ }
++ }
++ if (oldp) {
++ holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0);
++ if (holdp == NULL) {
++ return -TARGET_EFAULT;
++ }
++ }
++ holdlen = oldlen;
++ for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++) {
++ *q++ = tswap32(*p);
++ }
++ oidfmt(snamep, namelen, NULL, &kind);
++
++ /* Handle some arch/emulator dependent sysctl()'s here. */
++ switch (snamep[0]) {
++ case CTL_KERN:
++ switch (snamep[1]) {
++ case KERN_USRSTACK:
++#if 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;
++
++ case KERN_PROC:
++ switch (snamep[2]) {
++ case KERN_PROC_PATHNAME:
++ holdlen = strlen(ts->bprm->fullpath) + 1;
++ if (holdp) {
++ if (oldlen < holdlen) {
++ ret = -TARGET_EINVAL;
++ goto out;
++ }
++ strlcpy(holdp, ts->bprm->fullpath, oldlen);
++ }
++ ret = 0;
++ goto out;
++
++ default:
++ break;
++ }
++ break;
++
++ default:
++ break;
++ }
++ break;
++
++ case CTL_HW:
++ switch (snamep[1]) {
++ case HW_MACHINE:
++ strlcpy(holdp, TARGET_HW_MACHINE, oldlen);
++ ret = 0;
++ goto out;
++
++ case HW_MACHINE_ARCH:
++ strlcpy(holdp, TARGET_HW_MACHINE_ARCH, oldlen);
++ ret = 0;
++ goto out;
++
++ case 851: /* hw.availpages */
++ {
++ long lvalue;
++ size_t len = sizeof(lvalue);
++
++ if (sysctlbyname("hw.availpages", &lvalue, &len, NULL, 0)
++ == -1) {
++ ret = -1;
++ } else {
++ (*(abi_ulong *)holdp) = tswapal((abi_ulong)lvalue);
++ holdlen = sizeof(abi_ulong);
++ ret = 0;
++ }
++ }
++ goto out;
++
++ default:
++ break;
++ }
++ default:
++ break;
++ }
++
++ ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen));
++ 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:
++ if (oldlenp) {
++ put_user_ual(holdlen, oldlenp);
++ }
++ unlock_user(hnamep, namep, 0);
++ unlock_user(holdp, oldp, holdlen);
++ if (hnewp) {
++ unlock_user(hnewp, newp, 0);
++ }
++ g_free(snamep);
++ return ret;
++}
++
++/* sysarch() is architecture dependent. */
++abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2)
++{
++
++ return do_freebsd_arch_sysarch(cpu_env, arg1, arg2);
++}
+diff --git a/bsd-user/freebsd/os-thread.c b/bsd-user/freebsd/os-thread.c
+new file mode 100644
+index 0000000..6bf2a9f
+--- /dev/null
++++ b/bsd-user/freebsd/os-thread.c
+@@ -0,0 +1,1001 @@
++/*
++ * FreeBSD thr emulation support code
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/param.h>
++#include <sys/types.h>
++#include <sys/errno.h>
++#include <sys/mman.h>
++#include <sys/thr.h>
++#include <sys/umtx.h>
++#include <sys/rtprio.h>
++
++#include <machine/atomic.h>
++
++#include <time.h>
++
++#include "qemu.h"
++#include "qemu-os.h"
++#include "target_arch_cpu.h"
++#include "target_arch_thread.h"
++
++// #define DEBUG_UMTX(...) fprintf(stderr, __VA_ARGS__)
++#define DEBUG_UMTX(...)
++
++#define NEW_STACK_SIZE 0x40000
++
++/* sys/_umtx.h */
++struct target_umtx {
++ abi_ulong 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 {
++ uint32_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;
++};
++
++static pthread_mutex_t new_thread_lock = PTHREAD_MUTEX_INITIALIZER;
++pthread_mutex_t *new_freebsd_thread_lock_ptr = &new_thread_lock;
++
++static pthread_mutex_t umtx_wait_lck = PTHREAD_MUTEX_INITIALIZER;
++static pthread_cond_t umtx_wait_cv = PTHREAD_COND_INITIALIZER;
++static abi_ulong umtx_wait_addr;
++
++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;
++ }
++}
++
++void *new_freebsd_thread_start(void *arg)
++{
++ new_freebsd_thread_info_t *info = arg;
++ CPUArchState *env;
++ CPUState *cpu;
++ // TaskState *ts;
++ long tid;
++
++ env = info->env;
++ cpu = ENV_GET_CPU(env);
++ thread_cpu = cpu;
++
++ // ts = (TaskState *)env->opaque;
++ (void)thr_self(&tid);
++ cpu->host_tid = tid;
++ // ts->ts_tid = tid;
++
++ /* 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(info->parent_tid, info->param.parent_tid, abi_long);
++ }
++
++ /* Set arch dependent registers to start thread. */
++ target_thread_set_upcall(env, info->param.start_func, info->param.arg,
++ info->param.stack_base, info->param.stack_size);
++
++ /* Enable 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_freebsd_thread_lock_ptr);
++ pthread_mutex_unlock(new_freebsd_thread_lock_ptr);
++
++ cpu_loop(env);
++ /* never exits */
++
++ return NULL;
++}
++
++/*
++ * FreeBSD user mutex (_umtx) emulation
++ */
++static int tcmpset_al(abi_ulong *addr, abi_ulong a, abi_ulong b)
++{
++ 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);
++}
++
++abi_long freebsd_umtx_wait_uint(abi_ulong obj, uint32_t val,
++ struct timespec *timeout)
++{
++
++ DEBUG_UMTX("<WAIT> %s: _umtx_op(%p, %d, 0x%x, NULL, %p)\n",
++ __func__, g2h(obj), UMTX_OP_WAIT_UINT, val, timeout);
++ return get_errno(_umtx_op(g2h(obj), UMTX_OP_WAIT_UINT, val, NULL, timeout));
++}
++
++abi_long freebsd_umtx_wait_uint_private(abi_ulong obj, uint32_t val,
++ struct timespec *timeout)
++{
++
++ DEBUG_UMTX("<WAIT> %s: _umtx_op(%p, %d, 0x%x, NULL, %p)\n",
++ __func__, g2h(obj), UMTX_OP_WAIT_UINT_PRIVATE, val, timeout);
++ return get_errno(_umtx_op(g2h(obj), UMTX_OP_WAIT_UINT_PRIVATE, val, NULL,
++ timeout));
++}
++
++abi_long freebsd_umtx_wake_private(abi_ulong obj, uint32_t val)
++{
++
++ DEBUG_UMTX("<WAKE> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, g2h(obj), UMTX_OP_WAKE_PRIVATE, val);
++ return get_errno(_umtx_op(g2h(obj), UMTX_OP_WAKE_PRIVATE, val, NULL, NULL));
++}
++
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
++#if defined(UMTX_OP_NWAKE_PRIVATE)
++abi_long freebsd_umtx_nwake_private(abi_ulong obj, uint32_t val)
++{
++
++ DEBUG_UMTX("<NWAKE> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, g2h(obj), UMTX_OP_NWAKE_PRIVATE, val);
++ return get_errno(_umtx_op(g2h(obj), UMTX_OP_NWAKE_PRIVATE, val, NULL,
++ NULL));
++}
++#endif /* UMTX_OP_NWAKE_PRIVATE */
++
++#if defined(UMTX_OP_MUTEX_WAKE2)
++abi_long freebsd_umtx_mutex_wake2(abi_ulong target_addr,
++ __unused uint32_t flags)
++{
++ abi_long ret = 0;
++
++ pthread_mutex_lock(&umtx_wait_lck);
++ DEBUG_UMTX("<WAKE2 CV> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, g2h(target_addr), UMTX_OP_MUTEX_WAKE2, flags);
++ umtx_wait_addr = target_addr;
++ ret = get_errno(pthread_cond_broadcast(&umtx_wait_cv));
++ pthread_mutex_unlock(&umtx_wait_lck);
++
++ return ret;
++}
++#endif /* UMTX_OP_MUTEX_WAKE2 */
++
++abi_long freebsd_umtx_sem_wait(abi_ulong obj, struct timespec *timeout)
++{
++
++ /* XXX Assumes struct _usem is opauque to the user */
++ if (!access_ok(VERIFY_WRITE, obj, sizeof(struct target__usem))) {
++ return -TARGET_EFAULT;
++ }
++ return get_errno(_umtx_op(g2h(obj), UMTX_OP_SEM_WAIT, 0, NULL, timeout));
++}
++
++abi_long freebsd_umtx_sem_wake(abi_ulong obj, uint32_t val)
++{
++
++ return get_errno(_umtx_op(g2h(obj), UMTX_OP_SEM_WAKE, val, NULL, NULL));
++}
++#endif
++
++abi_long t2h_freebsd_rtprio(struct rtprio *host_rtp, abi_ulong target_addr)
++{
++ struct target_freebsd_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;
++}
++
++abi_long h2t_freebsd_rtprio(abi_ulong target_addr, struct rtprio *host_rtp)
++{
++ struct target_freebsd_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;
++}
++
++abi_long freebsd_lock_umtx(abi_ulong target_addr, abi_long id,
++ struct timespec *timeout)
++{
++ abi_long ret;
++ abi_long owner;
++
++ /*
++ * XXX Note that memory at umtx_addr can change and so we need to be
++ * careful and check for faults.
++ */
++ for (;;) {
++ 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);
++ DEBUG_UMTX("<WAIT> %s: _umtx_op(%p, %d, 0x%llx, NULL, NULL)\n",
++ __func__, g2h(target_addr), UMTX_OP_WAIT, (long long)owner);
++#ifdef TARGET_ABI32
++ ret = get_errno(_umtx_op(g2h(target_addr), UMTX_OP_WAIT_UINT, owner,
++ NULL, timeout));
++#else
++ ret = get_errno(_umtx_op(g2h(target_addr), UMTX_OP_WAIT, owner,
++ NULL, timeout));
++#endif
++ if (is_error(ret)) {
++ return ret;
++ }
++ }
++}
++
++abi_long freebsd_unlock_umtx(abi_ulong target_addr, abi_long id)
++{
++ abi_ulong owner;
++ struct target_umtx *target_umtx;
++
++ 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. */
++ DEBUG_UMTX("<WAKE> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, g2h(target_addr), UMTX_OP_WAKE, 0);
++ _umtx_op(g2h(target_addr), UMTX_OP_WAKE, 0, 0, 0);
++
++ return 0;
++}
++
++abi_long freebsd_umtx_wait(abi_ulong targ_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, targ_addr, sizeof(abi_ulong))) {
++ return -TARGET_EFAULT;
++ }
++
++ DEBUG_UMTX("<WAIT> %s: _umtx_op(%p, %d, 0x%llx, NULL, NULL)\n",
++ __func__, g2h(targ_addr), UMTX_OP_WAIT, (long long)id);
++#ifdef TARGET_ABI32
++ return get_errno(_umtx_op(g2h(targ_addr), UMTX_OP_WAIT_UINT, id, NULL, ts));
++#else
++ return get_errno(_umtx_op(g2h(targ_addr), UMTX_OP_WAIT, id, NULL, ts));
++#endif
++}
++
++abi_long freebsd_umtx_wake(abi_ulong target_addr, uint32_t n_wake)
++{
++
++ DEBUG_UMTX("<WAKE> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, g2h(target_addr), UMTX_OP_WAKE, n_wake);
++ return get_errno(_umtx_op(g2h(target_addr), UMTX_OP_WAKE, n_wake, NULL, 0));
++}
++
++abi_long freebsd_umtx_mutex_wake(abi_ulong obj, abi_long val)
++{
++
++ DEBUG_UMTX("<WAKE> %s: _umtx_op(%p, %d, 0x%llx, NULL, NULL)\n",
++ __func__, g2h(obj), UMTX_OP_WAKE, (long long)val);
++ return get_errno(_umtx_op(g2h(obj), UMTX_OP_MUTEX_WAKE, val, NULL, NULL));
++}
++
++abi_long freebsd_lock_umutex(abi_ulong target_addr, uint32_t id,
++ struct timespec *ts, int mode)
++{
++ uint32_t owner, flags;
++ int ret = 0;
++
++ for (;;) {
++ struct target_umutex *target_umutex;
++
++ pthread_mutex_lock(&umtx_wait_lck);
++
++ if (!lock_user_struct(VERIFY_WRITE, target_umutex, target_addr, 0)) {
++ pthread_mutex_unlock(&umtx_wait_lck);
++ return -TARGET_EFAULT;
++ }
++
++ __get_user(owner, &target_umutex->m_owner);
++
++ if (TARGET_UMUTEX_WAIT == mode) {
++ if (TARGET_UMUTEX_UNOWNED == owner ||
++ TARGET_UMUTEX_CONTESTED == owner) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ pthread_mutex_unlock(&umtx_wait_lck);
++ 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);
++ pthread_mutex_unlock(&umtx_wait_lck);
++ return 0;
++ }
++
++ /* 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)) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ pthread_mutex_unlock(&umtx_wait_lck);
++ return 0;
++ }
++ /* The lock changed so restart. */
++ unlock_user_struct(target_umutex, target_addr, 1);
++ pthread_mutex_unlock(&umtx_wait_lck);
++ continue;
++ }
++ }
++
++ __get_user(flags, &target_umutex->m_flags);
++ if ((flags & TARGET_UMUTEX_ERROR_CHECK) != 0 &&
++ (owner & ~TARGET_UMUTEX_CONTESTED) == id) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ pthread_mutex_unlock(&umtx_wait_lck);
++ return -TARGET_EDEADLK;
++ }
++
++ if (TARGET_UMUTEX_TRY == mode) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ pthread_mutex_unlock(&umtx_wait_lck);
++ return -TARGET_EBUSY;
++ }
++
++ /*
++ * If we caught a signal, we have retried and now
++ * exit immediately.
++ */
++ if (is_error(ret)) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ pthread_mutex_unlock(&umtx_wait_lck);
++ return ret;
++ }
++
++ /* 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);
++ pthread_mutex_unlock(&umtx_wait_lck);
++ continue;
++ }
++
++ DEBUG_UMTX("<WAIT CV> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, g2h(target_addr), UMTX_OP_WAIT_UINT,
++ tswap32(target_umutex->m_owner));
++ unlock_user_struct(target_umutex, target_addr, 1);
++
++again:
++ if (ts == NULL) {
++ ret = get_errno(pthread_cond_wait(&umtx_wait_cv,
++ &umtx_wait_lck));
++ } else {
++ ret = get_errno(pthread_cond_timedwait(&umtx_wait_cv,
++ &umtx_wait_lck, ts));
++ }
++ if (ret != 0) {
++ pthread_mutex_unlock(&umtx_wait_lck);
++ break;
++ }
++ if (target_addr != umtx_wait_addr) {
++ goto again;
++ }
++ pthread_mutex_unlock(&umtx_wait_lck);
++ }
++
++ return ret;
++}
++
++abi_long freebsd_unlock_umutex(abi_ulong target_addr, uint32_t id)
++{
++ struct target_umutex *target_umutex;
++ uint32_t owner;
++
++
++ if (!lock_user_struct(VERIFY_WRITE, target_umutex, target_addr, 0)) {
++ return -TARGET_EFAULT;
++ }
++ /* 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;
++ }
++ 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;
++ }
++ }
++ /* This is a contested lock. Unlock it. */
++ __put_user(TARGET_UMUTEX_UNOWNED, &target_umutex->m_owner);
++ unlock_user_struct(target_umutex, target_addr, 1);
++
++ /* And wake up all those contesting it. */
++ DEBUG_UMTX("<WAKE> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, g2h(target_addr), UMTX_OP_WAKE, 0);
++ return get_errno(_umtx_op(g2h(target_addr), UMTX_OP_WAKE, 0, 0, 0));
++}
++
++/*
++ * _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 } };
++
++
++/*
++ * wflags CVWAIT_CHECK_UNPARKING, CVWAIT_ABSTIME, CVWAIT_CLOCKID
++ */
++abi_long freebsd_cv_wait(abi_ulong target_ucond_addr,
++ abi_ulong target_umtx_addr, struct timespec *ts, int wflags)
++{
++ abi_long ret;
++ long tid;
++
++ if (!access_ok(VERIFY_WRITE, target_ucond_addr,
++ sizeof(struct target_ucond))) {
++ return -TARGET_EFAULT;
++ }
++
++ /* Check the clock ID if needed. */
++ if ((wflags & TARGET_CVWAIT_CLOCKID) != 0) {
++ struct target_ucond *target_ucond;
++ uint32_t clockid;
++
++ 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_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 = freebsd_unlock_umutex(target_umtx_addr, tid);
++ if (is_error(ret)) {
++ _umtx_op(&_cv_mutex, UMTX_OP_MUTEX_UNLOCK, 0, NULL, NULL);
++ return ret;
++ }
++
++ /* UMTX_OP_CV_WAIT unlocks _cv_mutex */
++ DEBUG_UMTX("<WAIT> %s: _umtx_op(%p, %d, 0x%x, %p, NULL)\n",
++ __func__, g2h(target_ucond_addr), UMTX_OP_CV_WAIT, wflags,
++ &_cv_mutex);
++ ret = get_errno(_umtx_op(g2h(target_ucond_addr), UMTX_OP_CV_WAIT, wflags,
++ &_cv_mutex, ts));
++
++ return ret;
++}
++
++abi_long freebsd_cv_signal(abi_ulong target_ucond_addr)
++{
++ abi_long 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);
++ DEBUG_UMTX("<WAKE> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, g2h(target_ucond_addr), UMTX_OP_CV_SIGNAL, 0);
++ 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;
++}
++
++abi_long freebsd_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);
++ DEBUG_UMTX("<WAKE> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, g2h(target_ucond_addr), UMTX_OP_CV_BROADCAST, 0);
++ 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;
++}
++
++abi_long freebsd_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;
++ abi_long 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);
++ DEBUG_UMTX("<WAIT> %s: _umtx_op(%p, %d, 0x%x (0x%x), NULL, NULL)\n",
++ __func__, &target_urwlock->rw_state,
++ UMTX_OP_WAIT_UINT, tswap32(state),
++ target_urwlock->rw_state);
++ ret = get_errno(_umtx_op(&target_urwlock->rw_state,
++ UMTX_OP_WAIT_UINT, tswap32(state), NULL, ts));
++ if (is_error(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 (blocked_readers == 1) {
++ /* 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);
++ }
++ }
++ }
++}
++
++abi_long freebsd_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;
++ abi_long 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) {
++ DEBUG_UMTX("<WAKE> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, &target_urwlock->rw_state, UMTX_OP_WAKE,
++ tswap32(state));
++ ret = get_errno(_umtx_op(&target_urwlock->rw_state,
++ 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);
++ DEBUG_UMTX("<WAIT> %s: _umtx_op(%p, %d, 0x%x(0x%x), NULL, NULL)\n",
++ __func__, &target_urwlock->rw_blocked_writers,
++ UMTX_OP_WAIT_UINT, tswap32(state),
++ target_urwlock->rw_state);
++ ret = get_errno(_umtx_op(&target_urwlock->rw_state,
++ UMTX_OP_WAIT_UINT, tswap32(state), NULL, ts));
++ if (is_error(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 (blocked_writers == 1) {
++ /* 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;
++ }
++ }
++}
++
++abi_long freebsd_rw_unlock(abi_ulong target_addr)
++{
++ struct target_urwlock *target_urwlock;
++ uint32_t flags, state, count = 0;
++
++ 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;
++ }
++
++ if (!(flags & TARGET_URWLOCK_PREFER_READER)) {
++ if (state & TARGET_URWLOCK_WRITE_WAITERS) {
++ count = 1;
++ } else if (state & TARGET_URWLOCK_READ_WAITERS) {
++ count = INT_MAX;
++ }
++ } else {
++ if (state & TARGET_URWLOCK_READ_WAITERS) {
++ count = INT_MAX;
++ } else if (state & TARGET_URWLOCK_WRITE_WAITERS) {
++ count = 1;
++ }
++ }
++
++ unlock_user_struct(target_urwlock, target_addr, 1);
++ if (count != 0) {
++ DEBUG_UMTX("<WAKE> %s: _umtx_op(%p, %d, 0x%x, NULL, NULL)\n",
++ __func__, &target_urwlock->rw_state, UMTX_OP_WAKE, count);
++ return get_errno(_umtx_op(&target_urwlock->rw_state, UMTX_OP_WAKE,
++ count, NULL, NULL));
++ } else {
++ return 0;
++ }
++}
++
++abi_long do_freebsd_thr_new(CPUArchState *env,
++ abi_ulong target_param_addr, int32_t param_size)
++{
++ new_freebsd_thread_info_t info;
++ pthread_attr_t attr;
++ TaskState *ts;
++ CPUArchState *new_env;
++ struct target_freebsd_thr_param *target_param;
++ abi_ulong target_rtp_addr;
++ struct target_freebsd_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);
++ info.param.flags = tswap32(target_param->flags);
++ target_rtp_addr = info.param.rtp = tswapal(target_param->rtp);
++ unlock_user(target_param, target_param_addr, 0);
++
++ thr_self(&info.parent_tid);
++
++ 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);
++ //target_cpu_reset(new_env); /* XXX called in cpu_copy()? */
++
++ /* init regs that differ from the parent thread. */
++ target_cpu_clone_regs(new_env, info.param.stack_base);
++ new_env->opaque = ts;
++ ts->bprm = parent_ts->bprm;
++ ts->info = parent_ts->info;
++
++ target_cpu_set_tls(new_env, info.param.tls_base);
++
++ /* Grab a mutex so that thread setup appears atomic. */
++ pthread_mutex_lock(new_freebsd_thread_lock_ptr);
++
++ pthread_mutex_init(&info.mutex, NULL);
++ pthread_mutex_lock(&info.mutex);
++ pthread_cond_init(&info.cond, NULL);
++ info.env = new_env;
++
++ /* XXX check return values... */
++ 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);
++
++ ret = pthread_create(&info.thread, &attr, new_freebsd_thread_start, &info);
++ /* XXX Free new CPU state if thread creation fails. */
++
++ sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
++ pthread_attr_destroy(&attr);
++ if (ret == 0) {
++ /* Wait for the child to initialize. */
++ pthread_cond_wait(&info.cond, &info.mutex);
++ } else {
++ /* Creation of new thread failed. */
++ ret = -host_to_target_errno(errno);
++ }
++
++ pthread_mutex_unlock(&info.mutex);
++ pthread_cond_destroy(&info.cond);
++ pthread_mutex_destroy(&info.mutex);
++ pthread_mutex_unlock(new_freebsd_thread_lock_ptr);
++
++ return ret;
++}
+diff --git a/bsd-user/freebsd/os-thread.h b/bsd-user/freebsd/os-thread.h
+new file mode 100644
+index 0000000..5e24852
+--- /dev/null
++++ b/bsd-user/freebsd/os-thread.h
+@@ -0,0 +1,511 @@
++/*
++ * FreeBSD thread and user mutex related system call shims
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef __FREEBSD_OS_THREAD_H_
++#define __FREEBSD_OS_THREAD_H_
++
++#include <sys/thr.h>
++#include <sys/rtprio.h>
++#include <sys/umtx.h>
++
++#include "qemu-os.h"
++
++static abi_long do_freebsd_thr_create(CPUArchState *env, abi_ulong target_ctx,
++ abi_ulong target_id, int flags)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_create()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_self(abi_ulong target_id)
++{
++ abi_long ret;
++ long tid;
++
++ ret = get_errno(thr_self(&tid));
++ if (!is_error(ret)) {
++ if (put_user_sal(tid, target_id)) {
++ return -TARGET_EFAULT;
++ }
++ }
++ return ret;
++}
++
++static abi_long do_freebsd_thr_exit(CPUArchState *cpu_env, abi_ulong tid_addr)
++{
++ CPUState *cpu = ENV_GET_CPU(cpu_env);
++ TaskState *ts;
++
++ /*
++ * XXX This probably breaks if a signal arrives.
++ * We should disable signals.
++ */
++ cpu_list_lock();
++ /* Remove the CPU from the list. */
++ QTAILQ_REMOVE(&cpus, cpu, node);
++ cpu_list_unlock();
++ if (tid_addr) {
++ /* Signal target userland that it can free the stack. */
++ if (!put_user_sal(1, tid_addr)) {
++ freebsd_umtx_wake(tid_addr, INT_MAX);
++ }
++ }
++ thread_cpu = NULL;
++ object_unref(OBJECT(ENV_GET_CPU(cpu_env)));
++ ts = ((CPUArchState *)cpu_env)->opaque;
++ g_free(ts);
++ pthread_exit(NULL);
++ /* Doesn't return */
++ return 0;
++}
++
++static abi_long do_freebsd_thr_kill(long id, int sig)
++{
++
++ return get_errno(thr_kill(id, sig));
++}
++
++static abi_long do_freebsd_thr_kill2(pid_t pid, long id, int sig)
++{
++
++ return get_errno(thr_kill2(pid, id, sig));
++}
++
++static abi_long do_freebsd_thr_suspend(abi_ulong target_ts)
++{
++ abi_long ret;
++ struct timespec ts;
++
++ if (target_ts != 0) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = thr_suspend(&ts);
++ } else {
++ ret = thr_suspend(NULL);
++ }
++ return ret;
++}
++
++static abi_long do_freebsd_thr_wake(long tid)
++{
++
++ return get_errno(thr_wake(tid));
++}
++
++static abi_long do_freebsd_thr_set_name(long tid, abi_ulong target_name)
++{
++ abi_long ret;
++ void *p;
++
++ p = lock_user_string(target_name);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = thr_set_name(tid, p);
++ unlock_user(p, target_name, 0);
++
++ return ret;
++}
++
++static abi_long do_freebsd_rtprio_thread(int function, lwpid_t lwpid,
++ abi_ulong target_addr)
++{
++ int ret;
++ struct rtprio rtp;
++
++ ret = t2h_freebsd_rtprio(&rtp, target_addr);
++ if (!is_error(ret)) {
++ ret = get_errno(rtprio_thread(function, lwpid, &rtp));
++ }
++ if (!is_error(ret)) {
++ ret = h2t_freebsd_rtprio(target_addr, &rtp);
++ }
++ return ret;
++}
++
++static abi_long do_freebsd_getcontext(void *cpu_env, abi_ulong arg1)
++{
++ abi_long ret;
++ target_ucontext_t *ucp;
++ sigset_t sigmask;
++
++ if (arg1 == 0) {
++ return -TARGET_EINVAL;
++ }
++ ret = get_errno(sigprocmask(0, NULL, &sigmask));
++ if (!is_error(ret)) {
++ ucp = lock_user(VERIFY_WRITE, arg1, sizeof(target_ucontext_t), 0);
++ if (ucp == 0) {
++ return -TARGET_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));
++ }
++ return ret;
++}
++
++static abi_long do_freebsd_setcontext(void *cpu_env, abi_ulong arg1)
++{
++ abi_long ret;
++ target_ucontext_t *ucp;
++ sigset_t sigmask;
++ if (arg1 == 0) {
++ return -TARGET_EINVAL;
++ }
++ ucp = lock_user(VERIFY_READ, arg1, sizeof(target_ucontext_t), 1);
++ if (ucp == 0) {
++ return -TARGET_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 (!is_error(ret)) {
++ (void)sigprocmask(SIG_SETMASK, &sigmask, NULL);
++ }
++ return ret;
++}
++
++/* swapcontext(2) */
++static abi_long do_freebsd_swapcontext(void *cpu_env, abi_ulong arg1,
++ abi_ulong arg2)
++{
++ abi_long ret;
++ target_ucontext_t *ucp;
++ sigset_t sigmask;
++
++ if (arg1 == 0 || arg2 == 0) {
++ return -TARGET_EINVAL;
++ }
++ /* Save current context in arg1. */
++ ret = get_errno(sigprocmask(0, NULL, &sigmask));
++ if (!is_error(ret)) {
++ ucp = lock_user(VERIFY_WRITE, arg1, sizeof(target_ucontext_t), 0);
++ if (ucp == 0) {
++ return -TARGET_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));
++ }
++ if (is_error(ret)) {
++ return ret;
++ }
++
++ /* Restore the context in arg2 to the current context. */
++ ucp = lock_user(VERIFY_READ, arg2, sizeof(target_ucontext_t), 1);
++ if (ucp == 0) {
++ return -TARGET_EFAULT;
++ }
++ ret = set_mcontext(cpu_env, &ucp->uc_mcontext, 0);
++ target_to_host_sigset(&sigmask, &ucp->uc_sigmask);
++ unlock_user(ucp, arg2, sizeof(target_ucontext_t));
++ if (!is_error(ret)) {
++ (void)sigprocmask(SIG_SETMASK, &sigmask, NULL);
++ }
++ return ret;
++}
++
++
++/* undocumented _umtx_lock() */
++static inline abi_long do_freebsd__umtx_lock(abi_ulong target_addr)
++{
++ abi_long ret;
++ long tid;
++
++ ret = get_errno(thr_self(&tid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ return freebsd_lock_umtx(target_addr, tid, NULL);
++}
++
++/* undocumented _umtx_unlock() */
++static inline abi_long do_freebsd__umtx_unlock(abi_ulong target_addr)
++{
++ abi_long ret;
++ long tid;
++
++ ret = get_errno(thr_self(&tid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ return freebsd_unlock_umtx(target_addr, tid);
++}
++
++/* undocumented _umtx_op(void *obj, int op, u_long val, void *uaddr,
++ void *target_ts); */
++static inline abi_long do_freebsd__umtx_op(abi_ulong obj, int op, abi_ulong val,
++ abi_ulong uaddr, abi_ulong target_ts)
++{
++ abi_long ret;
++ struct timespec ts;
++ long tid;
++
++ switch (op) {
++ case TARGET_UMTX_OP_LOCK:
++ ret = get_errno(thr_self(&tid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ if (target_ts != 0) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_lock_umtx(obj, tid, &ts);
++ } else {
++ ret = freebsd_lock_umtx(obj, tid, NULL);
++ }
++ break;
++
++ case TARGET_UMTX_OP_UNLOCK:
++ ret = get_errno(thr_self(&tid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ ret = freebsd_unlock_umtx(obj, tid);
++ break;
++
++ case TARGET_UMTX_OP_WAIT:
++ /* args: obj *, val, ts * */
++ if (target_ts != 0) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_umtx_wait(obj, tswapal(val), &ts);
++ } else {
++ ret = freebsd_umtx_wait(obj, tswapal(val), NULL);
++ }
++ break;
++
++ case TARGET_UMTX_OP_WAKE:
++ /* args: obj *, nr_wakeup */
++ ret = freebsd_umtx_wake(obj, val);
++ break;
++
++ case TARGET_UMTX_OP_MUTEX_LOCK:
++ ret = get_errno(thr_self(&tid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ if (target_ts) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_lock_umutex(obj, tid, &ts, 0);
++ } else {
++ ret = freebsd_lock_umutex(obj, tid, NULL, 0);
++ }
++ break;
++
++ case TARGET_UMTX_OP_MUTEX_UNLOCK:
++ ret = get_errno(thr_self(&tid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ ret = freebsd_unlock_umutex(obj, tid);
++ break;
++
++ case TARGET_UMTX_OP_MUTEX_TRYLOCK:
++ ret = get_errno(thr_self(&tid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ ret = freebsd_lock_umutex(obj, tid, NULL, TARGET_UMUTEX_TRY);
++ break;
++
++ case TARGET_UMTX_OP_MUTEX_WAIT:
++ ret = get_errno(thr_self(&tid));
++ if (is_error(ret)) {
++ return ret;
++ }
++ if (target_ts != 0) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_lock_umutex(obj, tid, &ts, TARGET_UMUTEX_WAIT);
++ } else {
++ ret = freebsd_lock_umutex(obj, tid, NULL, TARGET_UMUTEX_WAIT);
++ }
++ break;
++
++ case TARGET_UMTX_OP_MUTEX_WAKE:
++ /* Don't need to do access_ok(). */
++ ret = freebsd_umtx_mutex_wake(obj, val);
++ 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 != 0) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_cv_wait(obj, uaddr, &ts, val);
++ } else {
++ ret = freebsd_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 = freebsd_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 = freebsd_cv_broadcast(obj);
++ break;
++
++ case TARGET_UMTX_OP_WAIT_UINT:
++ if (!access_ok(VERIFY_READ, obj, sizeof(abi_ulong))) {
++ return -TARGET_EFAULT;
++ }
++ if (target_ts != 0) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_umtx_wait_uint(obj, tswap32((uint32_t)val), &ts);
++ } else {
++ ret = freebsd_umtx_wait_uint(obj, tswap32((uint32_t)val), NULL);
++ }
++ break;
++
++ case TARGET_UMTX_OP_WAIT_UINT_PRIVATE:
++ if (!access_ok(VERIFY_READ, obj, sizeof(abi_ulong))) {
++ return -TARGET_EFAULT;
++ }
++ if (target_ts != 0) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_umtx_wait_uint_private(obj, tswap32((uint32_t)val),
++ &ts);
++ } else {
++ ret = freebsd_umtx_wait_uint_private(obj, tswap32((uint32_t)val),
++ NULL);
++ }
++ break;
++
++ case TARGET_UMTX_OP_WAKE_PRIVATE:
++ /* Don't need to do access_ok(). */
++ ret = freebsd_umtx_wake_private(obj, val);
++ break;
++
++ case TARGET_UMTX_OP_RW_RDLOCK:
++ if (target_ts != 0) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_rw_rdlock(obj, val, &ts);
++ } else {
++ ret = freebsd_rw_rdlock(obj, val, NULL);
++ }
++ break;
++
++ case TARGET_UMTX_OP_RW_WRLOCK:
++ if (target_ts != 0) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_rw_wrlock(obj, val, &ts);
++ } else {
++ ret = freebsd_rw_wrlock(obj, val, NULL);
++ }
++ break;
++
++ case TARGET_UMTX_OP_RW_UNLOCK:
++ ret = freebsd_rw_unlock(obj);
++ break;
++
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
++#ifdef UMTX_OP_MUTEX_WAKE2
++ case TARGET_UMTX_OP_MUTEX_WAKE2:
++ ret = freebsd_umtx_mutex_wake2(obj, val);
++ break;
++#endif /* UMTX_OP_MUTEX_WAKE2 */
++
++#ifdef UMTX_OP_NWAKE_PRIVATE
++ case TARGET_UMTX_OP_NWAKE_PRIVATE:
++ {
++ int i;
++ abi_ulong *uaddr;
++ uint32_t imax = tswap32(INT_MAX);
++
++ if (!access_ok(VERIFY_READ, obj, val * sizeof(uint32_t))) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_umtx_nwake_private(obj, val);
++
++ uaddr = (abi_ulong *)g2h(obj);
++ ret = 0;
++ for (i = 0; i < (int32_t)val; i++) {
++ ret = freebsd_umtx_wake_private(tswapal(uaddr[i]), imax);
++ if (is_error(ret)) {
++ break;
++ }
++ }
++ }
++ break;
++#endif /* UMTX_OP_NWAKE_PRIVATE */
++
++ case TARGET_UMTX_OP_SEM_WAIT:
++ if (target_ts != 0) {
++ if (t2h_freebsd_timespec(&ts, target_ts)) {
++ return -TARGET_EFAULT;
++ }
++ ret = freebsd_umtx_sem_wait(obj, &ts);
++ } else {
++ ret = freebsd_umtx_sem_wait(obj, NULL);
++ }
++ break;
++
++ case TARGET_UMTX_OP_SEM_WAKE:
++ /* Don't need to do access_ok(). */
++ ret = freebsd_umtx_sem_wake(obj, val);
++ break;
++#endif
++ default:
++ return -TARGET_EINVAL;
++ }
++ return ret;
++}
++
++#endif /* !__FREEBSD_OS_THREAD_H_ */
+diff --git a/bsd-user/freebsd/os-time.c b/bsd-user/freebsd/os-time.c
+new file mode 100644
+index 0000000..7ac4397
+--- /dev/null
++++ b/bsd-user/freebsd/os-time.c
+@@ -0,0 +1,205 @@
++/*
++ * FreeBSD time related system call helpers
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <time.h>
++#include <sys/timex.h>
++#include <sys/select.h>
++
++#include "qemu.h"
++#include "qemu-os.h"
++
++/*
++ * FreeBSD time conversion functions
++ */
++abi_long t2h_freebsd_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;
++}
++
++abi_long h2t_freebsd_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;
++}
++
++abi_long t2h_freebsd_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;
++}
++
++abi_long h2t_freebsd_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;
++}
++
++abi_long t2h_freebsd_timex(struct timex *host_tx, abi_ulong target_tx_addr)
++{
++ struct target_freebsd_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;
++}
++
++abi_long h2t_freebsd_ntptimeval(abi_ulong target_ntv_addr,
++ struct ntptimeval *ntv)
++{
++ struct target_freebsd_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;
++}
++
++/*
++ * select(2) fdset copy functions
++ */
++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;
++ target_fds = lock_user(VERIFY_READ, target_fds_addr,
++ sizeof(abi_ulong) * nw, 1);
++ if (target_fds == NULL) {
++ 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;
++}
++
++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;
++}
++
++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;
++ target_fds = lock_user(VERIFY_WRITE, target_fds_addr,
++ sizeof(abi_ulong) * nw, 0);
++ if (target_fds == NULL) {
++ 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;
++}
++
+diff --git a/bsd-user/freebsd/os-time.h b/bsd-user/freebsd/os-time.h
+new file mode 100644
+index 0000000..c6b5b28
+--- /dev/null
++++ b/bsd-user/freebsd/os-time.h
+@@ -0,0 +1,643 @@
++/*
++ * FreeBSD time related system call shims
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __FREEBSD_OS_TIME_H_
++#define __FREEBSD_OS_TIME_H_
++
++#include <sys/types.h>
++#include <sys/event.h>
++#include <sys/select.h>
++#include <sys/timex.h>
++#include <signal.h>
++#include <time.h>
++
++#include "qemu-os.h"
++
++/* nanosleep(2) */
++static inline abi_long do_freebsd_nanosleep(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ struct timespec req, rem;
++
++ ret = t2h_freebsd_timespec(&req, arg1);
++ if (!is_error(ret)) {
++ ret = get_errno(nanosleep(&req, &rem));
++ if (!is_error(ret) && arg2) {
++ h2t_freebsd_timespec(arg2, &rem);
++ }
++ }
++
++ return ret;
++}
++
++/* clock_gettime(2) */
++static inline abi_long do_freebsd_clock_gettime(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ struct timespec ts;
++
++ ret = get_errno(clock_gettime(arg1, &ts));
++ if (!is_error(ret)) {
++ if (h2t_freebsd_timespec(arg2, &ts)) {
++ return -TARGET_EFAULT;
++ }
++ }
++
++ return ret;
++}
++
++/* clock_settime(2) */
++static inline abi_long do_freebsd_clock_settime(abi_long arg1, abi_long arg2)
++{
++ struct timespec ts;
++
++ if (t2h_freebsd_timespec(&ts, arg2) != 0) {
++ return -TARGET_EFAULT;
++ }
++
++ return get_errno(clock_settime(arg1, &ts));
++}
++
++/* clock_getres(2) */
++static inline abi_long do_freebsd_clock_getres(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ struct timespec ts;
++
++ ret = get_errno(clock_getres(arg1, &ts));
++ if (!is_error(ret)) {
++ if (h2t_freebsd_timespec(arg2, &ts)) {
++ return -TARGET_EFAULT;
++ }
++ }
++
++ return ret;
++}
++
++/* gettimeofday(2) */
++static inline abi_long do_freebsd_gettimeofday(abi_ulong arg1, abi_ulong arg2)
++{
++ abi_long ret;
++ struct timeval tv;
++ struct timezone tz, *target_tz; /* XXX */
++
++ if (arg2 != 0) {
++ if (!lock_user_struct(VERIFY_READ, target_tz, arg2, 0)) {
++ return -TARGET_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 (h2t_freebsd_timeval(&tv, arg1)) {
++ return -TARGET_EFAULT;
++ }
++ }
++
++ return ret;
++}
++
++/* settimeofday(2) */
++static inline abi_long do_freebsd_settimeofday(abi_long arg1, abi_long arg2)
++{
++ struct timeval tv;
++ struct timezone tz, *target_tz; /* XXX */
++
++ if (arg2 != 0) {
++ if (!lock_user_struct(VERIFY_READ, target_tz, arg2, 0)) {
++ return -TARGET_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 (t2h_freebsd_timeval(&tv, arg1)) {
++ return -TARGET_EFAULT;
++ }
++
++ return get_errno(settimeofday(&tv, arg2 != 0 ? &tz : NULL));
++}
++
++/* adjtime(2) */
++static inline abi_long do_freebsd_adjtime(abi_ulong target_delta_addr,
++ abi_ulong target_old_addr)
++{
++ abi_long ret;
++ struct timeval host_delta, host_old;
++
++ ret = t2h_freebsd_timeval(&host_delta, target_delta_addr);
++ if (is_error(ret)) {
++ return ret;
++ }
++
++ if (target_old_addr) {
++ ret = get_errno(adjtime(&host_delta, &host_old));
++ if (is_error(ret)) {
++ return ret;
++ }
++ ret = h2t_freebsd_timeval(&host_old, target_old_addr);
++ } else {
++ ret = get_errno(adjtime(&host_delta, NULL));
++ }
++
++ return ret;
++}
++
++/* ntp_adjtime(2) */
++static abi_long do_freebsd_ntp_adjtime(abi_ulong target_tx_addr)
++{
++ abi_long ret;
++ struct timex host_tx;
++
++ ret = t2h_freebsd_timex(&host_tx, target_tx_addr);
++ if (ret == 0) {
++ ret = get_errno(ntp_adjtime(&host_tx));
++ }
++
++ return ret;
++}
++
++/* ntp_gettime(2) */
++static abi_long do_freebsd_ntp_gettime(abi_ulong target_ntv_addr)
++{
++ abi_long ret;
++ struct ntptimeval host_ntv;
++
++ ret = get_errno(ntp_gettime(&host_ntv));
++ if (ret == 0) {
++ ret = h2t_freebsd_ntptimeval(target_ntv_addr, &host_ntv);
++ }
++
++ return ret;
++}
++
++
++/* utimes(2) */
++static inline abi_long do_freebsd_utimes(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ struct timeval *tvp, tv[2];
++
++ if (arg2 != 0) {
++ if (t2h_freebsd_timeval(&tv[0], arg2) ||
++ t2h_freebsd_timeval(&tv[1], arg2 +
++ sizeof(struct target_freebsd_timeval))) {
++ return -TARGET_EFAULT;
++ }
++ tvp = tv;
++ } else {
++ tvp = NULL;
++ }
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(utimes(p, tvp));
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* lutimes(2) */
++static inline abi_long do_freebsd_lutimes(abi_long arg1, abi_long arg2)
++{
++ abi_long ret;
++ void *p;
++ struct timeval *tvp, tv[2];
++
++ if (arg2 != 0) {
++ if (t2h_freebsd_timeval(&tv[0], arg2) ||
++ t2h_freebsd_timeval(&tv[1], arg2 +
++ sizeof(struct target_freebsd_timeval))) {
++ return -TARGET_EFAULT;
++ }
++ tvp = tv;
++ } else {
++ tvp = NULL;
++ }
++ p = lock_user_string(arg1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(lutimes(p, tvp));
++ unlock_user(p, arg1, 0);
++
++ return ret;
++}
++
++/* futimes(2) */
++static inline abi_long do_freebsd_futimes(abi_long arg1, abi_long arg2)
++{
++ struct timeval *tvp, tv[2];
++
++ if (arg2 != 0) {
++ if (t2h_freebsd_timeval(&tv[0], arg2) ||
++ t2h_freebsd_timeval(&tv[1], arg2 +
++ sizeof(struct target_freebsd_timeval))) {
++ return -TARGET_EFAULT;
++ }
++ tvp = tv;
++ } else {
++ tvp = NULL;
++ }
++
++ return get_errno(futimes(arg1, tvp));
++}
++
++/* futimesat(2) */
++static inline abi_long do_freebsd_futimesat(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++ abi_long ret;
++ void *p;
++ struct timeval *tvp, tv[2];
++
++ if (arg3 != 0) {
++ if (t2h_freebsd_timeval(&tv[0], arg3) ||
++ t2h_freebsd_timeval(&tv[1], arg3 +
++ sizeof(struct target_freebsd_timeval))) {
++ return -TARGET_EFAULT;
++ }
++ tvp = tv;
++ } else {
++ tvp = NULL;
++ }
++
++ p = lock_user_string(arg2);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ ret = get_errno(futimesat(arg1, p, tvp));
++ unlock_user(p, arg2, 0);
++
++ return ret;
++}
++
++/*
++ * undocumented ktimer_create(clockid_t clock_id, struct sigevent *evp,
++ * int *timerid) syscall
++ */
++static inline abi_long do_freebsd_ktimer_create(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall ktimer_create()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* undocumented ktimer_delete(int timerid) syscall */
++static inline abi_long do_freebsd_ktimer_delete(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall ktimer_delete()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * undocumented ktimer_settime(int timerid, int flags,
++ * const struct itimerspec *value, struct itimerspec *ovalue) syscall
++ */
++static inline abi_long do_freebsd_ktimer_settime(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall ktimer_settime()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * undocumented ktimer_gettime(int timerid, struct itimerspec *value)
++ * syscall
++ */
++static inline abi_long do_freebsd_ktimer_gettime(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall ktimer_gettime()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * undocumented ktimer_getoverrun(int timerid) syscall
++ */
++static inline abi_long do_freebsd_ktimer_getoverrun(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall ktimer_getoverrun()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* select(2) */
++static inline 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, error;
++
++ ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
++ if (ret != 0) {
++ return ret;
++ }
++ ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
++ if (ret != 0) {
++ return ret;
++ }
++ ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
++ if (ret != 0) {
++ return ret;
++ }
++
++ if (target_tv_addr != 0) {
++ if (t2h_freebsd_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 != 0) {
++ error = copy_to_user_fdset(rfd_addr, &rfds, n);
++ if (error != 0) {
++ return error;
++ }
++ }
++ if (wfd_addr != 0) {
++ error = copy_to_user_fdset(wfd_addr, &wfds, n);
++ if (error != 0) {
++ return error;
++ }
++ }
++ if (efd_addr != 0) {
++ error = copy_to_user_fdset(efd_addr, &efds, n);
++ if (error != 0) {
++ return error;
++ }
++ }
++ if (target_tv_addr != 0) {
++ error = h2t_freebsd_timeval(&tv, target_tv_addr);
++ if (is_error(error)) {
++ return error;
++ }
++ }
++ }
++ return ret;
++}
++
++/* pselect(2) */
++static inline 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 (is_error(ret)) {
++ return ret;
++ }
++ ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
++ if (is_error(ret)) {
++ return ret;
++ }
++ ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
++ if (is_error(ret)) {
++ return ret;
++ }
++
++ /* Unlike select(), pselect() uses struct timespec instead of timeval */
++ if (ts_addr) {
++ if (t2h_freebsd_timespec(&ts, ts_addr)) {
++ return -TARGET_EFAULT;
++ }
++ ts_ptr = &ts;
++ } else {
++ ts_ptr = NULL;
++ }
++
++ if (set_addr != 0) {
++ p = lock_user(VERIFY_READ, set_addr, sizeof(target_sigset_t), 1);
++ if (p == NULL) {
++ 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 != 0) {
++ ret = copy_to_user_fdset(rfd_addr, &rfds, n);
++ if (is_error(ret)) {
++ return ret;
++ }
++ }
++ if (wfd_addr != 0) {
++ ret = copy_to_user_fdset(wfd_addr, &wfds, n);
++ if (is_error(ret)) {
++ return ret;
++ }
++ }
++ if (efd_addr != 0) {
++ ret = copy_to_user_fdset(efd_addr, &efds, n);
++ if (is_error(ret)) {
++ return ret;
++ }
++ }
++ if (ts_addr != 0) {
++ ret = h2t_freebsd_timespec(ts_addr, &ts);
++ if (is_error(ret)) {
++ return ret;
++ }
++ }
++ }
++ return ret;
++}
++
++/* kqueue(2) */
++static inline abi_long do_freebsd_kqueue(void)
++{
++
++ return get_errno(kqueue());
++}
++
++/* kevent(2) */
++static inline abi_long do_freebsd_kevent(abi_long arg1, abi_ulong arg2,
++ abi_long arg3, abi_ulong arg4, abi_long arg5, abi_long arg6)
++{
++ abi_long ret;
++ struct kevent *changelist = NULL, *eventlist = NULL;
++ struct target_freebsd_kevent *target_changelist, *target_eventlist;
++ struct timespec ts;
++ int i;
++
++ if (arg3 != 0) {
++ target_changelist = lock_user(VERIFY_READ, arg2,
++ sizeof(struct target_freebsd_kevent) * arg3, 1);
++ if (target_changelist == NULL) {
++ return -TARGET_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);
++ /* __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 (t2h_freebsd_timespec(&ts, arg6)) {
++ return -TARGET_EFAULT;
++ }
++ }
++ ret = get_errno(kevent(arg1, changelist, arg3, eventlist, arg5,
++ arg6 != 0 ? &ts : NULL));
++ if (!is_error(ret)) {
++ target_eventlist = lock_user(VERIFY_WRITE, arg4,
++ sizeof(struct target_freebsd_kevent) * arg5, 0);
++ if (target_eventlist == NULL) {
++ return -TARGET_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_freebsd_kevent) * arg5);
++ }
++ return ret;
++}
++
++/* sigtimedwait(2) */
++static inline abi_long do_freebsd_sigtimedwait(abi_ulong arg1, abi_ulong arg2,
++ abi_ulong arg3)
++{
++ abi_long ret;
++ void *p;
++ sigset_t set;
++ struct timespec uts, *puts;
++ siginfo_t uinfo;
++
++ p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ target_to_host_sigset(&set, p);
++ unlock_user(p, arg1, 0);
++ if (arg3) {
++ puts = &uts;
++ t2h_freebsd_timespec(puts, arg3);
++ } else {
++ puts = NULL;
++ }
++ ret = get_errno(sigtimedwait(&set, &uinfo, puts));
++ if (!is_error(ret) && arg2) {
++ p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0);
++ if (p == NULL) {
++ return -TARGET_EFAULT;
++ }
++ host_to_target_siginfo(p, &uinfo);
++ unlock_user(p, arg2, sizeof(target_siginfo_t));
++ }
++ return ret;
++}
++
++/* setitimer(2) */
++static inline abi_long do_freebsd_setitimer(int arg1, abi_ulong arg2, abi_ulong arg3)
++{
++ abi_long ret = 0;
++ struct itimerval value, ovalue, *pvalue;
++
++ if (arg2) {
++ pvalue = &value;
++ if (t2h_freebsd_timeval(&pvalue->it_interval, arg2) ||
++ t2h_freebsd_timeval(&pvalue->it_value, arg2 + sizeof(struct target_freebsd_timeval))) {
++ return -TARGET_EFAULT;
++ }
++ } else {
++ pvalue = NULL;
++ }
++ ret = get_errno(setitimer(arg1, pvalue, &ovalue));
++ if (!is_error(ret) && arg3) {
++ if (h2t_freebsd_timeval(&ovalue.it_interval, arg3)
++ || h2t_freebsd_timeval(&ovalue.it_value, arg3 + sizeof(struct target_freebsd_timeval))) {
++ return -TARGET_EFAULT;
++ }
++ }
++ return ret;
++}
++
++/* getitimer(2) */
++static inline abi_long do_freebsd_getitimer(int arg1, abi_ulong arg2)
++{
++ abi_long ret = 0;
++ struct itimerval value;
++
++ ret = get_errno(getitimer(arg1, &value));
++ if (!is_error(ret) && arg2) {
++ if (h2t_freebsd_timeval(&value.it_interval, arg2) ||
++ h2t_freebsd_timeval(&value.it_value, arg2 + sizeof(struct target_freebsd_timeval))) {
++ return -TARGET_EFAULT;
++ }
++ }
++ return ret;
++}
++
++#endif /* __FREEBSD_OS_TIME_H_ */
+diff --git a/bsd-user/freebsd/qemu-os.h b/bsd-user/freebsd/qemu-os.h
+new file mode 100644
+index 0000000..7d79e52
+--- /dev/null
++++ b/bsd-user/freebsd/qemu-os.h
+@@ -0,0 +1,79 @@
++/*
++ * FreeBSD conversion extern declarations
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _QEMU_OS_H_
++#define _QEMU_OS_H_
++
++#include <sys/types.h>
++#include <sys/acl.h>
++#include <sys/mount.h>
++#include <sys/timex.h>
++#include <sys/rtprio.h>
++#include <sys/select.h>
++#include <sys/socket.h>
++#include <sys/stat.h>
++#include <netinet/in.h>
++
++#include <time.h>
++
++/* os-time.c */
++abi_long t2h_freebsd_timeval(struct timeval *tv, abi_ulong target_tv_addr);
++abi_long h2t_freebsd_timeval(struct timeval *tv, abi_ulong target_tv_addr);
++
++abi_long t2h_freebsd_timespec(struct timespec *ts, abi_ulong target_ts_addr);
++abi_long h2t_freebsd_timespec(abi_ulong target_ts_addr, struct timespec *ts);
++
++abi_long t2h_freebsd_timex(struct timex *host_tx, abi_ulong target_tx_addr);
++
++abi_long h2t_freebsd_ntptimeval(abi_ulong target_ntv_addr,
++ struct ntptimeval *ntv);
++
++abi_ulong copy_from_user_fdset(fd_set *fds, abi_ulong target_fds_addr, int n);
++abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
++ abi_ulong target_fds_addr, int n);
++abi_long copy_to_user_fdset(abi_ulong target_fds_addr, const fd_set *fds,
++ int n);
++
++/* os-socket.c */
++abi_long t2h_freebsd_cmsg(struct msghdr *msgh,
++ struct target_msghdr *target_msgh);
++abi_long h2t_freebsd_cmsg(struct target_msghdr *target_msgh,
++ struct msghdr *msgh);
++
++/* os-stat.c */
++abi_long h2t_freebsd_stat(abi_ulong target_addr, struct stat *host_st);
++abi_long h2t_freebsd_nstat(abi_ulong target_addr, struct stat *host_st);
++abi_long t2h_freebsd_fhandle(fhandle_t *host_fh, abi_ulong target_addr);
++abi_long h2t_freebsd_fhandle(abi_ulong target_addr, fhandle_t *host_fh);
++abi_long h2t_freebsd_statfs(abi_ulong target_addr, struct statfs *host_statfs);
++abi_long target_to_host_fcntl_cmd(int cmd);
++
++/* os-thread.c */
++abi_long t2h_freebsd_rtprio(struct rtprio *host_rtp, abi_ulong target_addr);
++abi_long h2t_freebsd_rtprio(abi_ulong target_addr, struct rtprio *host_rtp);
++abi_long do_freebsd_thr_new(CPUArchState *env, abi_ulong target_param_addr,
++ int32_t param_size);
++
++/* os-extattr.c */
++struct acl;
++abi_long t2h_freebsd_acl(struct acl *host_acl, abi_ulong target_addr);
++abi_long h2t_freebsd_acl(abi_ulong target_addr, struct acl *host_acl);
++abi_long t2h_freebsd_acl_type(acl_type_t *host_type, abi_long target_type);
++
++#endif /* !_QEMU_OS_H_ */
+diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list
+index 1edf412..ae2a4a3 100644
+--- a/bsd-user/freebsd/strace.list
++++ b/bsd-user/freebsd/strace.list
+@@ -1,7 +1,38 @@
++/*
++ * FreeBSD strace list
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++{ 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 },
+ { TARGET_FREEBSD_NR_acct, "acct", NULL, NULL, NULL },
+@@ -20,24 +51,41 @@
+ { 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 },
++{ 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_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 },
+ { 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 },
++{ 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 },
+@@ -63,7 +111,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 },
+@@ -72,6 +120,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 },
+@@ -96,7 +145,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 },
+@@ -116,6 +167,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 },
+@@ -123,6 +175,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 },
+@@ -151,15 +204,24 @@
+ { 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 },
+ { 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 },
++{ 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/freebsd/syscall_nr.h b/bsd-user/freebsd/syscall_nr.h
+index 36336ab..d849024 100644
+--- a/bsd-user/freebsd/syscall_nr.h
++++ b/bsd-user/freebsd/syscall_nr.h
+@@ -1,373 +1,450 @@
+ /*
+ * 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_killpg 146 /* COMPAT */
++#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/freebsd/target_os_elf.h b/bsd-user/freebsd/target_os_elf.h
+new file mode 100644
+index 0000000..67637a0
+--- /dev/null
++++ b/bsd-user/freebsd/target_os_elf.h
+@@ -0,0 +1,145 @@
++/*
++ * freebsd ELF definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_OS_ELF_H_
++#define _TARGET_OS_ELF_H_
++
++#include "target_arch_elf.h"
++#include "elf.h"
++
++/* this flag is uneffective under linux too, should be deleted */
++#ifndef MAP_DENYWRITE
++#define MAP_DENYWRITE 0
++#endif
++
++/* should probably go in elf.h */
++#ifndef ELIBBAD
++#define ELIBBAD 80
++#endif
++
++#ifndef ELF_PLATFORM
++#define ELF_PLATFORM (NULL)
++#endif
++
++#ifndef ELF_HWCAP
++#define ELF_HWCAP 0
++#endif
++
++#ifdef TARGET_ABI32
++#undef ELF_CLASS
++#define ELF_CLASS ELFCLASS32
++#undef bswaptls
++#define bswaptls(ptr) bswap32s(ptr)
++#endif
++
++struct exec
++{
++ unsigned int a_info; /* Use macros N_MAGIC, etc for access */
++ unsigned int a_text; /* length of text, in bytes */
++ unsigned int a_data; /* length of data, in bytes */
++ unsigned int a_bss; /* length of uninitialized data area, in bytes */
++ unsigned int a_syms; /* length of symbol table data in file, in bytes */
++ unsigned int a_entry; /* start address */
++ unsigned int a_trsize; /* length of relocation info for text, in bytes */
++ unsigned int a_drsize; /* length of relocation info for data, in bytes */
++};
++
++
++#define N_MAGIC(exec) ((exec).a_info & 0xffff)
++#define OMAGIC 0407
++#define NMAGIC 0410
++#define ZMAGIC 0413
++#define QMAGIC 0314
++
++/* max code+data+bss space allocated to elf interpreter */
++#define INTERP_MAP_SIZE (32 * 1024 * 1024)
++
++/* max code+data+bss+brk space allocated to ET_DYN executables */
++#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
++
++/* Necessary parameters */
++#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
++#define TARGET_ELF_PAGESTART(_v) ((_v) & \
++ ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
++#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
++
++#define INTERPRETER_NONE 0
++#define INTERPRETER_AOUT 1
++#define INTERPRETER_ELF 2
++
++#define DLINFO_ITEMS 12
++
++static abi_ulong target_create_elf_tables(abi_ulong p, int argc, int envc,
++ struct elfhdr * exec,
++ abi_ulong load_addr,
++ abi_ulong load_bias,
++ abi_ulong interp_load_addr, int ibcs,
++ struct image_info *info)
++{
++ abi_ulong sp;
++ int size;
++ const int n = sizeof(elf_addr_t);
++
++ sp = p;
++ /*
++ * Force 16 byte _final_ alignment here for generality.
++ */
++ sp = sp &~ (abi_ulong)15;
++ size = (DLINFO_ITEMS + 1) * 2;
++ size += envc + argc + 2;
++ size += (!ibcs ? 3 : 1); /* argc itself */
++ size *= n;
++ if (size & 15)
++ sp -= 16 - (size & 15);
++
++ /* This is correct because Linux defines
++ * elf_addr_t as Elf32_Off / Elf64_Off
++ */
++#define NEW_AUX_ENT(id, val) do { \
++ sp -= n; put_user_ual(val, sp); \
++ sp -= n; put_user_ual(id, sp); \
++ } while(0)
++
++ NEW_AUX_ENT (AT_NULL, 0);
++
++ /* There must be exactly DLINFO_ITEMS entries here. */
++ NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
++ NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
++ NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
++ NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
++ NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
++ NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
++ NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
++ NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
++ NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
++ NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
++ NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
++#ifdef ARCH_DLINFO
++ /*
++ * ARCH_DLINFO must come last so platform specific code can enforce
++ * special alignment requirements on the AUXV if necessary (eg. PPC).
++ */
++ ARCH_DLINFO;
++#endif
++#undef NEW_AUX_ENT
++
++ sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
++ return sp;
++}
++
++#endif /* _TARGET_OS_ELF_H_ */
+diff --git a/bsd-user/freebsd/target_os_siginfo.h b/bsd-user/freebsd/target_os_siginfo.h
+new file mode 100644
+index 0000000..39180ec
+--- /dev/null
++++ b/bsd-user/freebsd/target_os_siginfo.h
+@@ -0,0 +1,110 @@
++/*
++ * FreeBSD siginfo related definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_OS_SIGINFO_H_
++#define _TARGET_OS_SIGINFO_H_
++
++#define TARGET_NSIG 128
++#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
++#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
++
++/* 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 */
++ int32_t si_status; /* exit value */
++ 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;
++
++#define target_si_signo si_signo
++#define target_si_code si_code
++#define target_si_errno si_errno
++#define target_si_addr si_addr
++
++/* SIGILL si_codes */
++#define TARGET_ILL_ILLOPC (1) /* Illegal opcode. */
++#define TARGET_ILL_ILLOPN (2) /* Illegal operand. */
++#define TARGET_ILL_ILLADR (3) /* Illegal addressing mode. */
++#define TARGET_ILL_ILLTRP (4) /* Illegal trap. */
++#define TARGET_ILL_PRVOPC (5) /* Privileged opcode. */
++#define TARGET_ILL_PRVREG (6) /* Privileged register. */
++#define TARGET_ILL_COPROC (7) /* Coprocessor error. */
++#define TARGET_ILL_BADSTK (8) /* Internal stack error. */
++
++/* 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 */
++
++#endif /* !_TARGET_OS_SIGINFO_H_ */
+diff --git a/bsd-user/freebsd/target_os_signal.h b/bsd-user/freebsd/target_os_signal.h
+new file mode 100644
+index 0000000..d7004c8
+--- /dev/null
++++ b/bsd-user/freebsd/target_os_signal.h
+@@ -0,0 +1,79 @@
++#ifndef _TARGET_OS_SIGNAL_H_
++#define _TARGET_OS_SIGNAL_H_
++
++#include "target_os_siginfo.h"
++#include "target_arch_signal.h"
++
++/* Compare to sys/signal.h */
++#define TARGET_SIGHUP 1 /* hangup */
++#define TARGET_SIGINT 2 /* interrupt */
++#define TARGET_SIGQUIT 3 /* quit */
++#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught) */
++#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
++#define TARGET_SIGABRT 6 /* abort() */
++#define TARGET_SIGIOT SIGABRT /* compatibility */
++#define TARGET_SIGEMT 7 /* EMT instruction */
++#define TARGET_SIGFPE 8 /* floating point exception */
++#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
++#define TARGET_SIGBUS 10 /* bus error */
++#define TARGET_SIGSEGV 11 /* segmentation violation */
++#define TARGET_SIGSYS 12 /* bad argument to system call */
++#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
++#define TARGET_SIGALRM 14 /* alarm clock */
++#define TARGET_SIGTERM 15 /* software termination signal from kill */
++#define TARGET_SIGURG 16 /* urgent condition on IO channel */
++#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
++#define TARGET_SIGTSTP 18 /* stop signal from tty */
++#define TARGET_SIGCONT 19 /* continue a stopped process */
++#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
++#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
++#define TARGET_SIGTTOU 22 /* like TTIN for output if(tp->t_local&LTOSTOP)*/
++#define TARGET_SIGIO 23 /* input/output possible signal */
++#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
++#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
++#define TARGET_SIGVTALRM 26 /* virtual time alarm */
++#define TARGET_SIGPROF 27 /* profiling time alarm */
++#define TARGET_SIGWINCH 28 /* window size changes */
++#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 ((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 */
++#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
++#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering */
++#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1) */
++#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
++#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
++#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
++
++/*
++ * Flags for sigprocmask:
++ */
++#define TARGET_SIG_BLOCK 1 /* block specified signal set */
++#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
++#define TARGET_SIG_SETMASK 3 /* set specified signal set */
++
++#define TARGET_BADSIG SIG_ERR
++
++/*
++ * sigaltstack control
++ */
++#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
++#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack*/
++
++#endif /* !_TARGET_OS_SIGNAL_H_ */
+diff --git a/bsd-user/freebsd/target_os_stack.h b/bsd-user/freebsd/target_os_stack.h
+new file mode 100644
+index 0000000..c84b69e
+--- /dev/null
++++ b/bsd-user/freebsd/target_os_stack.h
+@@ -0,0 +1,157 @@
++#ifndef _TARGET_OS_STACK_H_
++#define _TARGET_OS_STACK_H_
++
++#include <sys/param.h>
++#include "target_arch_sigtramp.h"
++
++/*
++ * 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.)
++ * 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)
++ */
++static inline int setup_initial_stack(struct bsd_binprm *bprm,
++ abi_ulong *ret_addr)
++{
++ int i;
++ abi_ulong stack_hi_addr;
++ size_t execpath_len, stringspace;
++ abi_ulong destp, argvp, envp, p;
++ struct target_ps_strings ps_strs;
++ char canary[sizeof(abi_long) * 8];
++
++ stack_hi_addr = p = target_stkbas + target_stksiz;
++
++ /* Save some space for ps_strings. */
++ p -= sizeof(struct target_ps_strings);
++
++#ifdef TARGET_SZSIGCODE
++ /* Add machine depedent sigcode. */
++ p -= TARGET_SZSIGCODE;
++ if (setup_sigtramp(p, (unsigned)offsetof(struct target_sigframe, sf_uc),
++ TARGET_FREEBSD_NR_sigreturn)) {
++ errno = EFAULT;
++ return -1;
++ }
++#endif
++ if (bprm->fullpath) {
++ execpath_len = strlen(bprm->fullpath) + 1;
++ p -= roundup(execpath_len, sizeof(abi_ulong));
++ if (memcpy_to_target(p, bprm->fullpath, execpath_len)) {
++ errno = EFAULT;
++ return -1;
++ }
++ }
++ /* Add canary for SSP. */
++ arc4random_buf(canary, sizeof(canary));
++ p -= roundup(sizeof(canary), sizeof(abi_ulong));
++ if (memcpy_to_target(p, canary, sizeof(canary))) {
++ errno = EFAULT;
++ return -1;
++ }
++ /* Add page sizes array. */
++ /* p -= sizeof(int); */
++ p -= sizeof(abi_ulong);
++ /* if (put_user_u32(TARGET_PAGE_SIZE, p)) { */
++ if (put_user_ual(TARGET_PAGE_SIZE, p)) {
++ errno = EFAULT;
++ return -1;
++ }
++ /* Calculate the string space needed */
++ stringspace = 0;
++ for (i = 0; i < bprm->argc; ++i) {
++ stringspace += strlen(bprm->argv[i]) + 1;
++ }
++ for (i = 0; i < bprm->envc; ++i) {
++ stringspace += strlen(bprm->envp[i]) + 1;
++ }
++ if (stringspace > TARGET_ARG_MAX) {
++ errno = ENOMEM;
++ return -1;
++ }
++
++ /* Make room for the argv and envp strings */
++ /* p = destp = roundup(p - TARGET_SPACE_USRSPACE - (TARGET_ARG_MAX - stringspace), sizeof(abi_ulong)); */
++ argvp = p - TARGET_SPACE_USRSPACE;
++ p = destp = roundup(p - TARGET_SPACE_USRSPACE - TARGET_ARG_MAX, sizeof(abi_ulong));
++
++ /*
++ * Add argv strings. Note that the argv[] vectors are added by
++ * loader_build_argptr()
++ */
++ /* XXX need to make room for auxargs */
++ /* argvp = destp - ((bprm->argc + bprm->envc + 2) * sizeof(abi_ulong)); */
++ /* envp = argvp + (bprm->argc + 2) * sizeof(abi_ulong); */
++ envp = argvp + (bprm->argc + 1) * sizeof(abi_ulong);
++ ps_strs.ps_argvstr = tswapl(argvp);
++ ps_strs.ps_nargvstr = tswap32(bprm->argc);
++ for (i = 0; i < bprm->argc; ++i) {
++ size_t len = strlen(bprm->argv[i]) + 1;
++
++ if (memcpy_to_target(destp, bprm->argv[i], len)) {
++ errno = EFAULT;
++ return -1;
++ }
++ if (put_user_ual(destp, argvp)) {
++ errno = EFAULT;
++ return -1;
++ }
++ argvp += sizeof(abi_ulong);
++ destp += len;
++ }
++ if (put_user_ual(0, argvp)) {
++ errno = EFAULT;
++ return -1;
++ }
++ /*
++ * 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);
++ for (i = 0; i < bprm->envc; ++i) {
++ size_t len = strlen(bprm->envp[i]) + 1;
++
++ if (memcpy_to_target(destp, bprm->envp[i], len)) {
++ errno = EFAULT;
++ return -1;
++ }
++ if (put_user_ual(destp, envp)) {
++ errno = EFAULT;
++ return -1;
++ }
++ envp += sizeof(abi_ulong);
++ destp += len;
++ }
++ if (put_user_ual(0, envp)) {
++ errno = EFAULT;
++ return -1;
++ }
++ if (memcpy_to_target(stack_hi_addr - sizeof(ps_strs), &ps_strs,
++ sizeof(ps_strs))) {
++ errno = EFAULT;
++ return -1;
++ }
++
++ if (ret_addr) {
++ *ret_addr = p;
++ }
++
++ return 0;
++ }
++
++#endif /* !_TARGET_OS_STACK_H_ */
+diff --git a/bsd-user/freebsd/target_os_thread.h b/bsd-user/freebsd/target_os_thread.h
+new file mode 100644
+index 0000000..519aad8
+--- /dev/null
++++ b/bsd-user/freebsd/target_os_thread.h
+@@ -0,0 +1,6 @@
++#ifndef _TARGET_OS_THREAD_H_
++#define _TARGET_OS_THREAD_H_
++
++#include "target_arch_thread.h"
++
++#endif /* !_TARGET_OS_THREAD_H_ */
+diff --git a/bsd-user/freebsd/target_os_vmparam.h b/bsd-user/freebsd/target_os_vmparam.h
+new file mode 100644
+index 0000000..80ac6c8
+--- /dev/null
++++ b/bsd-user/freebsd/target_os_vmparam.h
+@@ -0,0 +1,23 @@
++#ifndef _TARGET_OS_VMPARAM_H_
++#define _TARGET_OS_VMPARAM_H_
++
++#include "target_arch_vmparam.h"
++
++#define TARGET_SPACE_USRSPACE 4096
++#define TARGET_ARG_MAX 262144
++
++/* Compare to sys/exec.h */
++struct target_ps_strings {
++ abi_ulong ps_argvstr;
++ uint32_t ps_nargvstr;
++ abi_ulong ps_envstr;
++ uint32_t ps_nenvstr;
++};
++
++extern abi_ulong target_stkbas;
++extern abi_ulong target_stksiz;
++
++#define TARGET_PS_STRINGS ((target_stkbas + target_stksiz) - \
++ sizeof(struct target_ps_strings))
++
++#endif /* !TARGET_OS_VMPARAM_H_ */
+diff --git a/bsd-user/i386/syscall.h b/bsd-user/i386/syscall.h
+index 9b34c61..52de302 100644
+--- a/bsd-user/i386/syscall.h
++++ b/bsd-user/i386/syscall.h
+@@ -1,3 +1,23 @@
++/*
++ * i386 system call definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _I386_SYSCALL_H_
++#define _I386_SYSCALL_H_
++
+ /* default linux values for the selectors */
+ #define __USER_CS (0x23)
+ #define __USER_DS (0x2B)
+@@ -158,4 +178,7 @@ struct target_vm86plus_struct {
+
+
+ #define UNAME_MACHINE "i386"
++#define TARGET_HW_MACHINE UNAME_MACHINE
++#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE
+
++#endif /* ! _I386_SYSCALL_H_ */
+diff --git a/bsd-user/i386/target_arch.h b/bsd-user/i386/target_arch.h
+new file mode 100644
+index 0000000..4cb398c
+--- /dev/null
++++ b/bsd-user/i386/target_arch.h
+@@ -0,0 +1,13 @@
++
++#ifndef _TARGET_ARCH_H_
++#define _TARGET_ARCH_H_
++
++/* target_arch_cpu.c */
++void bsd_i386_write_dt(void *ptr, unsigned long addr, unsigned long limit,
++ int flags);
++void bsd_i386_set_idt(int n, unsigned int dpl);
++void bsd_i386_set_idt_base(uint64_t base);
++
++#define target_cpu_set_tls(env, newtls)
++
++#endif /* ! _TARGET_ARCH_H_ */
+diff --git a/bsd-user/i386/target_arch_cpu.c b/bsd-user/i386/target_arch_cpu.c
+new file mode 100644
+index 0000000..2e0eec0
+--- /dev/null
++++ b/bsd-user/i386/target_arch_cpu.c
+@@ -0,0 +1,79 @@
++/*
++ * i386 cpu related code
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++
++#include "cpu.h"
++#include "qemu.h"
++#include "qemu/timer.h"
++
++#include "target_arch.h"
++
++static uint64_t *idt_table;
++
++/* CPUX86 core interface */
++void cpu_smm_update(CPUX86State *env)
++{
++}
++
++uint64_t cpu_get_tsc(CPUX86State *env)
++{
++ return cpu_get_real_ticks();
++}
++
++int cpu_get_pic_interrupt(CPUX86State *env)
++{
++ return -1;
++}
++
++void bsd_i386_write_dt(void *ptr, unsigned long addr, unsigned long limit,
++ int flags)
++{
++ unsigned int e1, e2;
++ uint32_t *p;
++ e1 = (addr << 16) | (limit & 0xffff);
++ e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
++ e2 |= flags;
++ p = ptr;
++ p[0] = tswap32(e1);
++ p[1] = tswap32(e2);
++}
++
++
++static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
++ uint32_t addr, unsigned int sel)
++{
++ uint32_t *p, e1, e2;
++ e1 = (addr & 0xffff) | (sel << 16);
++ e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
++ p = ptr;
++ p[0] = tswap32(e1);
++ p[1] = tswap32(e2);
++}
++
++/* only dpl matters as we do only user space emulation */
++void bsd_i386_set_idt(int n, unsigned int dpl)
++{
++ set_gate(idt_table + n, 0, dpl, 0, 0);
++}
++
++void bsd_i386_set_idt_base(uint64_t base)
++{
++ idt_table = g2h(base);
++}
++
+diff --git a/bsd-user/i386/target_arch_cpu.h b/bsd-user/i386/target_arch_cpu.h
+new file mode 100644
+index 0000000..c3df814
+--- /dev/null
++++ b/bsd-user/i386/target_arch_cpu.h
+@@ -0,0 +1,302 @@
++/*
++ * i386 cpu init and loop
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _TARGET_ARCH_CPU_H_
++#define _TARGET_ARCH_CPU_H_
++
++#include "target_arch.h"
++
++#define TARGET_DEFAULT_CPU_MODEL "qemu32"
++
++#define TARGET_CPU_RESET(env)
++
++static inline void target_cpu_init(CPUX86State *env,
++ struct target_pt_regs *regs)
++{
++ uint64_t *gdt_table;
++
++ cpu_x86_set_cpl(env, 3);
++
++ env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
++ env->hflags |= HF_PE_MASK;
++ if (env->features[FEAT_1_EDX] & CPUID_SSE) {
++ env->cr[4] |= CR4_OSFXSR_MASK;
++ env->hflags |= HF_OSFXSR_MASK;
++ }
++
++ /* flags setup : we activate the IRQs by default as in user mode */
++ env->eflags |= IF_MASK;
++
++ /* register setup */
++ env->regs[R_EAX] = regs->eax;
++ env->regs[R_EBX] = regs->ebx;
++ env->regs[R_ECX] = regs->ecx;
++ env->regs[R_EDX] = regs->edx;
++ env->regs[R_ESI] = regs->esi;
++ env->regs[R_EDI] = regs->edi;
++ env->regs[R_EBP] = regs->ebp;
++ env->regs[R_ESP] = regs->esp;
++ env->eip = regs->eip;
++
++ /* interrupt setup */
++ env->idt.limit = 255;
++
++ env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
++ PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
++ bsd_i386_set_idt_base(env->idt.base);
++ bsd_i386_set_idt(0, 0);
++ bsd_i386_set_idt(1, 0);
++ bsd_i386_set_idt(2, 0);
++ bsd_i386_set_idt(3, 3);
++ bsd_i386_set_idt(4, 3);
++ bsd_i386_set_idt(5, 0);
++ bsd_i386_set_idt(6, 0);
++ bsd_i386_set_idt(7, 0);
++ bsd_i386_set_idt(8, 0);
++ bsd_i386_set_idt(9, 0);
++ bsd_i386_set_idt(10, 0);
++ bsd_i386_set_idt(11, 0);
++ bsd_i386_set_idt(12, 0);
++ bsd_i386_set_idt(13, 0);
++ bsd_i386_set_idt(14, 0);
++ bsd_i386_set_idt(15, 0);
++ bsd_i386_set_idt(16, 0);
++ bsd_i386_set_idt(17, 0);
++ bsd_i386_set_idt(18, 0);
++ bsd_i386_set_idt(19, 0);
++ bsd_i386_set_idt(0x80, 3);
++
++ /* segment setup */
++ env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
++ PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
++ env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
++ gdt_table = g2h(env->gdt.base);
++
++ bsd_i386_write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
++ DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
++ (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
++
++ bsd_i386_write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
++ DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
++ (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
++
++ cpu_x86_load_seg(env, R_CS, __USER_CS);
++ cpu_x86_load_seg(env, R_SS, __USER_DS);
++ cpu_x86_load_seg(env, R_DS, __USER_DS);
++ cpu_x86_load_seg(env, R_ES, __USER_DS);
++ cpu_x86_load_seg(env, R_FS, __USER_DS);
++ cpu_x86_load_seg(env, R_GS, __USER_DS);
++ /* This hack makes Wine work... */
++ env->segs[R_FS].selector = 0;
++}
++
++static inline void target_cpu_loop(CPUX86State *env)
++{
++ int trapnr;
++ abi_ulong pc;
++ /* target_siginfo_t info; */
++
++ for (;;) {
++ trapnr = cpu_x86_exec(env);
++ switch (trapnr) {
++ case 0x80:
++ /* syscall from int $0x80 */
++ if (bsd_type == target_freebsd) {
++ abi_ulong params = (abi_ulong) env->regs[R_ESP] +
++ sizeof(int32_t);
++ int32_t syscall_nr = env->regs[R_EAX];
++ int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
++
++ if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
++ get_user_s32(syscall_nr, params);
++ params += sizeof(int32_t);
++ } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
++ get_user_s32(syscall_nr, params);
++ params += sizeof(int64_t);
++ }
++ get_user_s32(arg1, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg2, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg3, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg4, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg5, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg6, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg7, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg8, params);
++ env->regs[R_EAX] = do_freebsd_syscall(env,
++ syscall_nr,
++ arg1,
++ arg2,
++ arg3,
++ arg4,
++ arg5,
++ arg6,
++ arg7,
++ arg8);
++ } else { /* if (bsd_type == target_openbsd) */
++ env->regs[R_EAX] = do_openbsd_syscall(env,
++ env->regs[R_EAX],
++ env->regs[R_EBX],
++ env->regs[R_ECX],
++ env->regs[R_EDX],
++ env->regs[R_ESI],
++ env->regs[R_EDI],
++ env->regs[R_EBP]);
++ }
++ if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
++ env->regs[R_EAX] = -env->regs[R_EAX];
++ env->eflags |= CC_C;
++ } else {
++ env->eflags &= ~CC_C;
++ }
++ break;
++
++#if 0
++ case EXCP0B_NOSEG:
++ case EXCP0C_STACK:
++ info.si_signo = SIGBUS;
++ info.si_errno = 0;
++ info.si_code = TARGET_SI_KERNEL;
++ info._sifields._sigfault._addr = 0;
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP0D_GPF:
++ /* XXX: potential problem if ABI32 */
++ if (env->eflags & VM_MASK) {
++ handle_vm86_fault(env);
++ } else {
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ info.si_code = TARGET_SI_KERNEL;
++ info._sifields._sigfault._addr = 0;
++ queue_signal(env, info.si_signo, &info);
++ }
++ break;
++
++ case EXCP0E_PAGE:
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ if (!(env->error_code & 1)) {
++ info.si_code = TARGET_SEGV_MAPERR;
++ } else {
++ info.si_code = TARGET_SEGV_ACCERR;
++ }
++ info._sifields._sigfault._addr = env->cr[2];
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP00_DIVZ:
++ if (env->eflags & VM_MASK) {
++ handle_vm86_trap(env, trapnr);
++ } else {
++ /* division by zero */
++ info.si_signo = SIGFPE;
++ info.si_errno = 0;
++ info.si_code = TARGET_FPE_INTDIV;
++ info._sifields._sigfault._addr = env->eip;
++ queue_signal(env, info.si_signo, &info);
++ }
++ break;
++
++ case EXCP01_DB:
++ case EXCP03_INT3:
++ if (env->eflags & VM_MASK) {
++ handle_vm86_trap(env, trapnr);
++ } else {
++ info.si_signo = SIGTRAP;
++ info.si_errno = 0;
++ if (trapnr == EXCP01_DB) {
++ info.si_code = TARGET_TRAP_BRKPT;
++ info._sifields._sigfault._addr = env->eip;
++ } else {
++ info.si_code = TARGET_SI_KERNEL;
++ info._sifields._sigfault._addr = 0;
++ }
++ queue_signal(env, info.si_signo, &info);
++ }
++ break;
++
++ case EXCP04_INTO:
++ case EXCP05_BOUND:
++ if (env->eflags & VM_MASK) {
++ handle_vm86_trap(env, trapnr);
++ } else {
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ info.si_code = TARGET_SI_KERNEL;
++ info._sifields._sigfault._addr = 0;
++ queue_signal(env, info.si_signo, &info);
++ }
++ break;
++
++ case EXCP06_ILLOP:
++ info.si_signo = SIGILL;
++ info.si_errno = 0;
++ info.si_code = TARGET_ILL_ILLOPN;
++ info._sifields._sigfault._addr = env->eip;
++ queue_signal(env, info.si_signo, &info);
++ break;
++#endif
++ case EXCP_INTERRUPT:
++ /* just indicate that signals should be handled asap */
++ break;
++#if 0
++ case EXCP_DEBUG:
++ {
++ 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;
++#endif
++ default:
++ pc = env->segs[R_CS].base + env->eip;
++ fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
++ "aborting\n", (long)pc, trapnr);
++ abort();
++ }
++ process_pending_signals(env);
++ }
++}
++
++static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
++{
++ if (newsp)
++ env->regs[R_ESP] = newsp;
++ env->regs[R_EAX] = 0;
++}
++
++static inline void target_cpu_reset(CPUArchState *cpu)
++{
++ cpu_reset(ENV_GET_CPU(cpu));
++}
++
++#endif /* ! _TARGET_ARCH_CPU_H_ */
+diff --git a/bsd-user/i386/target_arch_elf.h b/bsd-user/i386/target_arch_elf.h
+new file mode 100644
+index 0000000..83b2197
+--- /dev/null
++++ b/bsd-user/i386/target_arch_elf.h
+@@ -0,0 +1,62 @@
++/*
++ * i386 ELF definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_ELF_H_
++#define _TARGET_ARCH_ELF_H_
++
++#define ELF_START_MMAP 0x80000000
++
++/*
++ * This is used to ensure we don't load something for the wrong architecture.
++ */
++#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
++
++/*
++ * These are used to set parameters in the core dumps.
++ */
++#define ELF_CLASS ELFCLASS32
++#define ELF_DATA ELFDATA2LSB
++#define ELF_ARCH EM_386
++
++#define USE_ELF_CORE_DUMP
++#define ELF_EXEC_PAGESIZE 4096
++
++/* XXX */
++#ifndef __FreeBSD__
++#define ELF_PLATFORM target_elf_get_platform()
++
++static const char *target_elf_get_platform(void)
++{
++ static char elf_platform[] = "i386";
++ int family = (thread_env->cpuid_version >> 8) & 0xff;
++ if (family > 6)
++ family = 6;
++ if (family >= 3)
++ elf_platform[1] = '0' + family;
++ return elf_platform;
++}
++
++#define ELF_HWCAP target_elf_get_hwcap()
++
++static uint32_t target_elf_get_hwcap(void)
++{
++ return thread_env->features[FEAT_1_EDX];
++}
++#endif /* ! __FreeBSD__ */
++
++#endif /* _TARGET_ARCH_ELF_H_ */
+diff --git a/bsd-user/i386/target_arch_signal.h b/bsd-user/i386/target_arch_signal.h
+new file mode 100644
+index 0000000..e2387b2
+--- /dev/null
++++ b/bsd-user/i386/target_arch_signal.h
+@@ -0,0 +1,94 @@
++/*
++ * i386 dependent signal definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef TARGET_ARCH_SIGNAL_H
++#define TARGET_ARCH_SIGNAL_H
++
++#include "cpu.h"
++
++/* Size of the signal trampolin code placed on the stack. */
++/* #define TARGET_SZSIGCODE (0) */ /* XXX to be added. */
++
++/* compare to x86/include/_limits.h */
++#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
++#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
++
++#define TARGET_MC_GET_CLEAR_RET 0x0001
++
++struct target_sigcontext {
++ /* to be added */
++};
++
++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 {
++ 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];
++};
++
++/*
++ * Compare to i386/i386/machdep.c sendsig()
++ * Assumes that target stack frame memory is locked.
++ */
++static inline abi_long set_sigtramp_args(CPUX86State *regs,
++ int sig, struct target_sigframe *frame, abi_ulong frame_addr,
++ struct target_sigaction *ka)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++/* Compare to i386/i386/machdep.c get_mcontext() */
++static inline abi_long get_mcontext(CPUX86State *regs,
++ target_mcontext_t *mcp, int flags)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++/* Compare to i386/i386/machdep.c set_mcontext() */
++static inline abi_long set_mcontext(CPUX86State *regs,
++ target_mcontext_t *mcp, int srflag)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++static inline abi_long get_ucontext_sigreturn(CPUX86State *regs,
++ abi_ulong target_sf, abi_ulong *target_uc)
++{
++ /* XXX */
++ *target_uc = 0;
++ return -TARGET_EOPNOTSUPP;
++}
++
++#endif /* TARGET_ARCH_SIGNAL_H */
+diff --git a/bsd-user/i386/target_arch_sigtramp.h b/bsd-user/i386/target_arch_sigtramp.h
+new file mode 100644
+index 0000000..f0f36d1
+--- /dev/null
++++ b/bsd-user/i386/target_arch_sigtramp.h
+@@ -0,0 +1,11 @@
++
++#ifndef _TARGET_ARCH_SIGTRAMP_H_
++#define _TARGET_ARCH_SIGTRAMP_H_
++
++static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
++ unsigned sys_sigreturn)
++{
++
++ return -TARGET_EOPNOTSUPP;
++}
++#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
+diff --git a/bsd-user/i386/target_arch_sysarch.h b/bsd-user/i386/target_arch_sysarch.h
+new file mode 100644
+index 0000000..4fa6698
+--- /dev/null
++++ b/bsd-user/i386/target_arch_sysarch.h
+@@ -0,0 +1,78 @@
++/*
++ * i386 sysarch system call emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __ARCH_SYSARCH_H_
++#define __ARCH_SYSARCH_H_
++
++#include "syscall.h"
++
++static inline abi_long do_freebsd_arch_sysarch(CPUX86State *env, int op,
++ abi_ulong parms)
++{
++ abi_long ret = 0;
++ abi_ulong val;
++ int idx;
++
++ switch (op) {
++ case TARGET_FREEBSD_I386_SET_GSBASE:
++ case TARGET_FREEBSD_I386_SET_FSBASE:
++ if (op == TARGET_FREEBSD_I386_SET_GSBASE) {
++ idx = R_GS;
++ } else {
++ idx = R_FS;
++ }
++ if (get_user(val, parms, abi_ulong)) {
++ return -TARGET_EFAULT;
++ }
++ cpu_x86_load_seg(env, idx, 0);
++ env->segs[idx].base = val;
++ break;
++
++ case TARGET_FREEBSD_I386_GET_GSBASE:
++ case TARGET_FREEBSD_I386_GET_FSBASE:
++ if (op == TARGET_FREEBSD_I386_GET_GSBASE) {
++ idx = R_GS;
++ } else {
++ idx = R_FS;
++ }
++ val = env->segs[idx].base;
++ if (put_user(val, parms, abi_ulong)) {
++ return -TARGET_EFAULT;
++ }
++ break;
++
++ /* XXX handle the others... */
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++ return ret;
++}
++
++static inline void do_freebsd_arch_print_sysarch(
++ const struct syscallname *name, abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
++{
++
++ gemu_log("%s(%d, " TARGET_ABI_FMT_lx ", " TARGET_ABI_FMT_lx ", "
++ TARGET_ABI_FMT_lx ")", name->name, (int)arg1, arg2, arg3, arg4);
++}
++
++#endif /* !__ARCH_SYSARCH_H_ */
++
+diff --git a/bsd-user/i386/target_arch_thread.h b/bsd-user/i386/target_arch_thread.h
+new file mode 100644
+index 0000000..407aa6c
+--- /dev/null
++++ b/bsd-user/i386/target_arch_thread.h
+@@ -0,0 +1,45 @@
++/*
++ * i386 thread support
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_THREAD_H_
++#define _TARGET_ARCH_THREAD_H_
++
++/* Compare to vm_machdep.c cpu_set_upcall_kse() */
++static inline void target_thread_set_upcall(CPUX86State *regs, abi_ulong entry,
++ abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
++{
++ /* XXX */
++}
++
++static inline void target_thread_init(struct target_pt_regs *regs,
++ struct image_info *infop)
++{
++ regs->esp = infop->start_stack;
++ regs->eip = infop->entry;
++
++ /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
++ starts %edx contains a pointer to a function which might be
++ registered using `atexit'. This provides a mean for the
++ dynamic linker to call DT_FINI functions for shared libraries
++ that have been loaded before the code runs.
++
++ A value of 0 tells we have no such handler. */
++ regs->edx = 0;
++}
++
++#endif /* !_TARGET_ARCH_THREAD_H_ */
+diff --git a/bsd-user/i386/target_arch_vmparam.h b/bsd-user/i386/target_arch_vmparam.h
+new file mode 100644
+index 0000000..f15af91
+--- /dev/null
++++ b/bsd-user/i386/target_arch_vmparam.h
+@@ -0,0 +1,28 @@
++#ifndef _TARGET_ARCH_VMPARAM_H_
++#define _TARGET_ARCH_VMPARAM_H_
++
++#include "cpu.h"
++
++/* compare to i386/include/vmparam.h */
++#define TARGET_MAXTSIZ (128UL*1024*1024) /* max text size */
++#define TARGET_DFLDSIZ (128UL*1024*1024) /* initial data size limit */
++#define TARGET_MAXDSIZ (512UL*1024*1024) /* max data size */
++#define TARGET_DFLSSIZ (8UL*1024*1024) /* initial stack size limit */
++#define TARGET_MAXSSIZ (64UL*1024*1024) /* max stack size */
++#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */
++
++#define TARGET_RESERVED_VA 0xf7000000
++
++#define TARGET_USRSTACK (0xbfc00000)
++
++static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
++{
++ return state->regs[R_ESP];
++}
++
++static inline void set_second_rval(CPUX86State *state, abi_ulong retval2)
++{
++ state->regs[R_EDX] = retval2;
++}
++
++#endif /* !_TARGET_ARCH_VMPARAM_H_ */
+diff --git a/bsd-user/i386/target_signal.h b/bsd-user/i386/target_signal.h
+index 2ef36d1..5491687 100644
+--- a/bsd-user/i386/target_signal.h
++++ b/bsd-user/i386/target_signal.h
+@@ -11,10 +11,4 @@ typedef struct target_sigaltstack {
+ abi_ulong ss_size;
+ } target_stack_t;
+
+-
+-static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+-{
+- return state->regs[R_ESP];
+-}
+-
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/main.c b/bsd-user/main.c
+index f81ba55..f27fcbc 100644
+--- a/bsd-user/main.c
++++ b/bsd-user/main.c
+@@ -1,7 +1,8 @@
+ /*
+- * qemu user main
++ * qemu bsd user main
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
++ * Copyright (c) 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
+@@ -23,652 +24,183 @@
+ #include <errno.h>
+ #include <unistd.h>
+ #include <machine/trap.h>
++#include <sys/syscall.h>
+ #include <sys/types.h>
+ #include <sys/mman.h>
+
+ #include "qemu.h"
+ #include "qemu-common.h"
+-/* For tb_lock */
+ #include "cpu.h"
+ #include "tcg.h"
+ #include "qemu/timer.h"
+ #include "qemu/envlist.h"
+
++#include "host_os.h"
++#include "target_arch_cpu.h"
++
+ int singlestep;
+-#if defined(CONFIG_USE_GUEST_BASE)
++static const char *cpu_model;
+ unsigned long mmap_min_addr;
++#if defined(CONFIG_USE_GUEST_BASE)
+ unsigned long guest_base;
+ int have_guest_base;
++#if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64)
++/*
++ * When running 32-on-64 we should make sure we can fit all of the possible
++ * guest address space into a contiguous chunk of virtual host memory.
++ *
++ * This way we will never overlap with our own libraries or binaries or stack
++ * or anything else that QEMU maps.
++ */
++unsigned long reserved_va = TARGET_RESERVED_VA;
++#else
+ unsigned long reserved_va;
+ #endif
++#endif /* CONFIG_USE_GUEST_BASE */
+
+ static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
+ const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
+ extern char **environ;
+ enum BSDType bsd_type;
+
+-/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
+- we allocate a bigger stack. Need a better solution, for example
+- by remapping the process stack directly at the right place */
+-unsigned long x86_stack_size = 512 * 1024;
+-
+-void gemu_log(const char *fmt, ...)
+-{
+- va_list ap;
+-
+- va_start(ap, fmt);
+- vfprintf(stderr, fmt, ap);
+- va_end(ap);
+-}
+-
+-#if defined(TARGET_I386)
+-int cpu_get_pic_interrupt(CPUX86State *env)
+-{
+- return -1;
+-}
+-#endif
+-
+-/* These are no-ops because we are not threadsafe. */
+-static inline void cpu_exec_start(CPUArchState *env)
+-{
+-}
++unsigned long target_maxtsiz = TARGET_MAXTSIZ; /* max text size */
++unsigned long target_dfldsiz = TARGET_DFLDSIZ; /* initial data size limit */
++unsigned long target_maxdsiz = TARGET_MAXDSIZ; /* max data size */
++unsigned long target_dflssiz = TARGET_DFLSSIZ; /* initial data size limit */
++unsigned long target_maxssiz = TARGET_MAXSSIZ; /* max stack size */
++unsigned long target_sgrowsiz = TARGET_SGROWSIZ; /* amount to grow stack */
+
+-static inline void cpu_exec_end(CPUArchState *env)
+-{
+-}
++char qemu_proc_pathname[PATH_MAX]; /* full path to exeutable */
+
+-static inline void start_exclusive(void)
+-{
+-}
++/* Helper routines for implementing atomic operations. */
+
+-static inline void end_exclusive(void)
+-{
+-}
++/*
++ * 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(&tcg_ctx.tb_ctx.tb_lock);
++ pthread_mutex_lock(&exclusive_lock);
++ mmap_fork_start();
+ }
+
+ void fork_end(int child)
+ {
++ mmap_fork_end(child);
+ if (child) {
++ CPUState *cpu, *next_cpu;
++ /*
++ * Child processes created by fork() only have a single thread.
++ * Discard information about the parent threads.
++ */
++ CPU_FOREACH_SAFE(cpu, next_cpu) {
++ if (cpu != thread_cpu) {
++ QTAILQ_REMOVE(&cpus, thread_cpu, node);
++ }
++ }
++ 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(&tcg_ctx.tb_ctx.tb_lock, NULL);
+ gdbserver_fork((CPUArchState *)thread_cpu->env_ptr);
++ } else {
++ pthread_mutex_unlock(&exclusive_lock);
++ pthread_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock);
+ }
+ }
+
+-void cpu_list_lock(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);
++ }
+ }
+
+-void cpu_list_unlock(void)
++/* Start an exclusive operation. Must only be called outside of cpu_exec. */
++void start_exclusive(void)
+ {
+-}
++ CPUState *other_cpu;
+
+-#ifdef TARGET_I386
+-/***********************************************************/
+-/* CPUX86 core interface */
++ pthread_mutex_lock(&exclusive_lock);
++ exclusive_idle();
+
+-void cpu_smm_update(CPUX86State *env)
+-{
+-}
+-
+-uint64_t cpu_get_tsc(CPUX86State *env)
+-{
+- return cpu_get_real_ticks();
++ pending_cpus = 1;
++ /* Make all other cpus stop executing. */
++ CPU_FOREACH(other_cpu) {
++ if (other_cpu->running) {
++ pending_cpus++;
++ cpu_exit(other_cpu);
++ }
++ }
++ if (pending_cpus > 1) {
++ pthread_cond_wait(&exclusive_cond, &exclusive_lock);
++ }
+ }
+
+-static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
+- int flags)
++/* Finish an exclusive operation. */
++void end_exclusive(void)
+ {
+- unsigned int e1, e2;
+- uint32_t *p;
+- e1 = (addr << 16) | (limit & 0xffff);
+- e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
+- e2 |= flags;
+- p = ptr;
+- p[0] = tswap32(e1);
+- p[1] = tswap32(e2);
++ pending_cpus = 0;
++ pthread_cond_broadcast(&exclusive_resume);
++ pthread_mutex_unlock(&exclusive_lock);
+ }
+
+-static uint64_t *idt_table;
+-#ifdef TARGET_X86_64
+-static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
+- uint64_t addr, unsigned int sel)
+-{
+- uint32_t *p, e1, e2;
+- e1 = (addr & 0xffff) | (sel << 16);
+- e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
+- p = ptr;
+- p[0] = tswap32(e1);
+- p[1] = tswap32(e2);
+- p[2] = tswap32(addr >> 32);
+- p[3] = 0;
+-}
+-/* only dpl matters as we do only user space emulation */
+-static void set_idt(int n, unsigned int dpl)
++/* Wait for exclusive ops to finish, and begin cpu execution. */
++void cpu_exec_start(CPUState *cpu)
+ {
+- set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
+-}
+-#else
+-static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
+- uint32_t addr, unsigned int sel)
+-{
+- uint32_t *p, e1, e2;
+- e1 = (addr & 0xffff) | (sel << 16);
+- e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
+- p = ptr;
+- p[0] = tswap32(e1);
+- p[1] = tswap32(e2);
++ pthread_mutex_lock(&exclusive_lock);
++ exclusive_idle();
++ cpu->running = true;
++ pthread_mutex_unlock(&exclusive_lock);
+ }
+
+-/* only dpl matters as we do only user space emulation */
+-static void set_idt(int n, unsigned int dpl)
++/* Mark cpu as not excuting, and release pending exclusive ops. */
++void cpu_exec_end(CPUState *cpu)
+ {
+- set_gate(idt_table + n, 0, dpl, 0, 0);
+-}
+-#endif
+-
+-void cpu_loop(CPUX86State *env)
+-{
+- int trapnr;
+- abi_ulong pc;
+- //target_siginfo_t info;
+-
+- for(;;) {
+- trapnr = cpu_x86_exec(env);
+- switch(trapnr) {
+- case 0x80:
+- /* syscall from int $0x80 */
+- if (bsd_type == target_freebsd) {
+- abi_ulong params = (abi_ulong) env->regs[R_ESP] +
+- sizeof(int32_t);
+- int32_t syscall_nr = env->regs[R_EAX];
+- int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
+-
+- if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
+- get_user_s32(syscall_nr, params);
+- params += sizeof(int32_t);
+- } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
+- get_user_s32(syscall_nr, params);
+- params += sizeof(int64_t);
+- }
+- get_user_s32(arg1, params);
+- params += sizeof(int32_t);
+- get_user_s32(arg2, params);
+- params += sizeof(int32_t);
+- get_user_s32(arg3, params);
+- params += sizeof(int32_t);
+- get_user_s32(arg4, params);
+- params += sizeof(int32_t);
+- get_user_s32(arg5, params);
+- params += sizeof(int32_t);
+- get_user_s32(arg6, params);
+- params += sizeof(int32_t);
+- get_user_s32(arg7, params);
+- params += sizeof(int32_t);
+- get_user_s32(arg8, params);
+- env->regs[R_EAX] = do_freebsd_syscall(env,
+- syscall_nr,
+- arg1,
+- arg2,
+- arg3,
+- arg4,
+- arg5,
+- arg6,
+- arg7,
+- arg8);
+- } else { //if (bsd_type == target_openbsd)
+- env->regs[R_EAX] = do_openbsd_syscall(env,
+- env->regs[R_EAX],
+- env->regs[R_EBX],
+- env->regs[R_ECX],
+- env->regs[R_EDX],
+- env->regs[R_ESI],
+- env->regs[R_EDI],
+- env->regs[R_EBP]);
+- }
+- if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
+- env->regs[R_EAX] = -env->regs[R_EAX];
+- env->eflags |= CC_C;
+- } else {
+- env->eflags &= ~CC_C;
+- }
+- break;
+-#ifndef TARGET_ABI32
+- case EXCP_SYSCALL:
+- /* syscall from syscall instruction */
+- if (bsd_type == target_freebsd)
+- env->regs[R_EAX] = do_freebsd_syscall(env,
+- env->regs[R_EAX],
+- env->regs[R_EDI],
+- env->regs[R_ESI],
+- env->regs[R_EDX],
+- env->regs[R_ECX],
+- env->regs[8],
+- env->regs[9], 0, 0);
+- else { //if (bsd_type == target_openbsd)
+- env->regs[R_EAX] = do_openbsd_syscall(env,
+- env->regs[R_EAX],
+- env->regs[R_EDI],
+- env->regs[R_ESI],
+- env->regs[R_EDX],
+- env->regs[10],
+- env->regs[8],
+- env->regs[9]);
+- }
+- env->eip = env->exception_next_eip;
+- if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
+- env->regs[R_EAX] = -env->regs[R_EAX];
+- env->eflags |= CC_C;
+- } else {
+- env->eflags &= ~CC_C;
+- }
+- break;
+-#endif
+-#if 0
+- case EXCP0B_NOSEG:
+- case EXCP0C_STACK:
+- info.si_signo = SIGBUS;
+- info.si_errno = 0;
+- info.si_code = TARGET_SI_KERNEL;
+- info._sifields._sigfault._addr = 0;
+- queue_signal(env, info.si_signo, &info);
+- break;
+- case EXCP0D_GPF:
+- /* XXX: potential problem if ABI32 */
+-#ifndef TARGET_X86_64
+- if (env->eflags & VM_MASK) {
+- handle_vm86_fault(env);
+- } else
+-#endif
+- {
+- info.si_signo = SIGSEGV;
+- info.si_errno = 0;
+- info.si_code = TARGET_SI_KERNEL;
+- info._sifields._sigfault._addr = 0;
+- queue_signal(env, info.si_signo, &info);
+- }
+- break;
+- case EXCP0E_PAGE:
+- info.si_signo = SIGSEGV;
+- info.si_errno = 0;
+- if (!(env->error_code & 1))
+- info.si_code = TARGET_SEGV_MAPERR;
+- else
+- info.si_code = TARGET_SEGV_ACCERR;
+- info._sifields._sigfault._addr = env->cr[2];
+- queue_signal(env, info.si_signo, &info);
+- break;
+- case EXCP00_DIVZ:
+-#ifndef TARGET_X86_64
+- if (env->eflags & VM_MASK) {
+- handle_vm86_trap(env, trapnr);
+- } else
+-#endif
+- {
+- /* division by zero */
+- info.si_signo = SIGFPE;
+- info.si_errno = 0;
+- info.si_code = TARGET_FPE_INTDIV;
+- info._sifields._sigfault._addr = env->eip;
+- queue_signal(env, info.si_signo, &info);
+- }
+- break;
+- case EXCP01_DB:
+- case EXCP03_INT3:
+-#ifndef TARGET_X86_64
+- if (env->eflags & VM_MASK) {
+- handle_vm86_trap(env, trapnr);
+- } else
+-#endif
+- {
+- info.si_signo = SIGTRAP;
+- info.si_errno = 0;
+- if (trapnr == EXCP01_DB) {
+- info.si_code = TARGET_TRAP_BRKPT;
+- info._sifields._sigfault._addr = env->eip;
+- } else {
+- info.si_code = TARGET_SI_KERNEL;
+- info._sifields._sigfault._addr = 0;
+- }
+- queue_signal(env, info.si_signo, &info);
+- }
+- break;
+- case EXCP04_INTO:
+- case EXCP05_BOUND:
+-#ifndef TARGET_X86_64
+- if (env->eflags & VM_MASK) {
+- handle_vm86_trap(env, trapnr);
+- } else
+-#endif
+- {
+- info.si_signo = SIGSEGV;
+- info.si_errno = 0;
+- info.si_code = TARGET_SI_KERNEL;
+- info._sifields._sigfault._addr = 0;
+- queue_signal(env, info.si_signo, &info);
+- }
+- break;
+- case EXCP06_ILLOP:
+- info.si_signo = SIGILL;
+- info.si_errno = 0;
+- info.si_code = TARGET_ILL_ILLOPN;
+- info._sifields._sigfault._addr = env->eip;
+- queue_signal(env, info.si_signo, &info);
+- break;
+-#endif
+- case EXCP_INTERRUPT:
+- /* just indicate that signals should be handled asap */
+- break;
+-#if 0
+- case EXCP_DEBUG:
+- {
+- 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;
+-#endif
+- default:
+- pc = env->segs[R_CS].base + env->eip;
+- fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
+- (long)pc, trapnr);
+- abort();
++ pthread_mutex_lock(&exclusive_lock);
++ cpu->running = false;
++ if (pending_cpus > 1) {
++ pending_cpus--;
++ if (pending_cpus == 1) {
++ pthread_cond_signal(&exclusive_cond);
+ }
+- process_pending_signals(env);
+ }
++ exclusive_idle();
++ pthread_mutex_unlock(&exclusive_lock);
+ }
+-#endif
+-
+-#ifdef TARGET_SPARC
+-#define SPARC64_STACK_BIAS 2047
+-
+-//#define DEBUG_WIN
+-/* WARNING: dealing with register windows _is_ complicated. More info
+- can be found at http://www.sics.se/~psm/sparcstack.html */
+-static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
+-{
+- index = (index + cwp * 16) % (16 * env->nwindows);
+- /* wrap handling : if cwp is on the last window, then we use the
+- registers 'after' the end */
+- if (index < 8 && env->cwp == env->nwindows - 1)
+- index += 16 * env->nwindows;
+- return index;
+-}
+-
+-/* save the register window 'cwp1' */
+-static inline void save_window_offset(CPUSPARCState *env, int cwp1)
+-{
+- unsigned int i;
+- abi_ulong sp_ptr;
+
+- sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
+-#ifdef TARGET_SPARC64
+- if (sp_ptr & 3)
+- sp_ptr += SPARC64_STACK_BIAS;
+-#endif
+-#if defined(DEBUG_WIN)
+- printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
+- sp_ptr, cwp1);
+-#endif
+- for(i = 0; i < 16; i++) {
+- /* FIXME - what to do if put_user() fails? */
+- put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
+- sp_ptr += sizeof(abi_ulong);
+- }
+-}
+-
+-static void save_window(CPUSPARCState *env)
++void cpu_list_lock(void)
+ {
+-#ifndef TARGET_SPARC64
+- unsigned int new_wim;
+- new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
+- ((1LL << env->nwindows) - 1);
+- save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
+- env->wim = new_wim;
+-#else
+- save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
+- env->cansave++;
+- env->canrestore--;
+-#endif
++ pthread_mutex_lock(&cpu_list_mutex);
+ }
+
+-static void restore_window(CPUSPARCState *env)
+-{
+-#ifndef TARGET_SPARC64
+- unsigned int new_wim;
+-#endif
+- unsigned int i, cwp1;
+- abi_ulong sp_ptr;
+-
+-#ifndef TARGET_SPARC64
+- new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
+- ((1LL << env->nwindows) - 1);
+-#endif
+-
+- /* restore the invalid window */
+- cwp1 = cpu_cwp_inc(env, env->cwp + 1);
+- sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
+-#ifdef TARGET_SPARC64
+- if (sp_ptr & 3)
+- sp_ptr += SPARC64_STACK_BIAS;
+-#endif
+-#if defined(DEBUG_WIN)
+- printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
+- sp_ptr, cwp1);
+-#endif
+- for(i = 0; i < 16; i++) {
+- /* FIXME - what to do if get_user() fails? */
+- get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
+- sp_ptr += sizeof(abi_ulong);
+- }
+-#ifdef TARGET_SPARC64
+- env->canrestore++;
+- if (env->cleanwin < env->nwindows - 1)
+- env->cleanwin++;
+- env->cansave--;
+-#else
+- env->wim = new_wim;
+-#endif
+-}
+-
+-static void flush_windows(CPUSPARCState *env)
++void cpu_list_unlock(void)
+ {
+- int offset, cwp1;
+-
+- offset = 1;
+- for(;;) {
+- /* if restore would invoke restore_window(), then we can stop */
+- cwp1 = cpu_cwp_inc(env, env->cwp + offset);
+-#ifndef TARGET_SPARC64
+- if (env->wim & (1 << cwp1))
+- break;
+-#else
+- if (env->canrestore == 0)
+- break;
+- env->cansave++;
+- env->canrestore--;
+-#endif
+- save_window_offset(env, cwp1);
+- offset++;
+- }
+- cwp1 = cpu_cwp_inc(env, env->cwp + 1);
+-#ifndef TARGET_SPARC64
+- /* set wim so that restore will reload the registers */
+- env->wim = 1 << cwp1;
+-#endif
+-#if defined(DEBUG_WIN)
+- printf("flush_windows: nb=%d\n", offset - 1);
+-#endif
++ pthread_mutex_unlock(&cpu_list_mutex);
+ }
+
+-void cpu_loop(CPUSPARCState *env)
++void cpu_loop(CPUArchState *env)
+ {
+- CPUState *cs = CPU(sparc_env_get_cpu(env));
+- int trapnr, ret, syscall_nr;
+- //target_siginfo_t info;
+
+- while (1) {
+- trapnr = cpu_sparc_exec (env);
+-
+- switch (trapnr) {
+-#ifndef TARGET_SPARC64
+- case 0x80:
+-#else
+- /* FreeBSD uses 0x141 for syscalls too */
+- case 0x141:
+- if (bsd_type != target_freebsd)
+- goto badtrap;
+- case 0x100:
+-#endif
+- syscall_nr = env->gregs[1];
+- if (bsd_type == target_freebsd)
+- ret = do_freebsd_syscall(env, syscall_nr,
+- env->regwptr[0], env->regwptr[1],
+- env->regwptr[2], env->regwptr[3],
+- env->regwptr[4], env->regwptr[5], 0, 0);
+- else if (bsd_type == target_netbsd)
+- ret = do_netbsd_syscall(env, syscall_nr,
+- env->regwptr[0], env->regwptr[1],
+- env->regwptr[2], env->regwptr[3],
+- env->regwptr[4], env->regwptr[5]);
+- else { //if (bsd_type == target_openbsd)
+-#if defined(TARGET_SPARC64)
+- syscall_nr &= ~(TARGET_OPENBSD_SYSCALL_G7RFLAG |
+- TARGET_OPENBSD_SYSCALL_G2RFLAG);
+-#endif
+- ret = do_openbsd_syscall(env, syscall_nr,
+- env->regwptr[0], env->regwptr[1],
+- env->regwptr[2], env->regwptr[3],
+- env->regwptr[4], env->regwptr[5]);
+- }
+- if ((unsigned int)ret >= (unsigned int)(-515)) {
+- ret = -ret;
+-#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
+- env->xcc |= PSR_CARRY;
+-#else
+- env->psr |= PSR_CARRY;
+-#endif
+- } else {
+-#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
+- env->xcc &= ~PSR_CARRY;
+-#else
+- env->psr &= ~PSR_CARRY;
+-#endif
+- }
+- env->regwptr[0] = ret;
+- /* next instruction */
+-#if defined(TARGET_SPARC64)
+- if (bsd_type == target_openbsd &&
+- env->gregs[1] & TARGET_OPENBSD_SYSCALL_G2RFLAG) {
+- env->pc = env->gregs[2];
+- env->npc = env->pc + 4;
+- } else if (bsd_type == target_openbsd &&
+- env->gregs[1] & TARGET_OPENBSD_SYSCALL_G7RFLAG) {
+- env->pc = env->gregs[7];
+- env->npc = env->pc + 4;
+- } else {
+- env->pc = env->npc;
+- env->npc = env->npc + 4;
+- }
+-#else
+- env->pc = env->npc;
+- env->npc = env->npc + 4;
+-#endif
+- break;
+- case 0x83: /* flush windows */
+-#ifdef TARGET_ABI32
+- case 0x103:
+-#endif
+- flush_windows(env);
+- /* next instruction */
+- env->pc = env->npc;
+- env->npc = env->npc + 4;
+- break;
+-#ifndef TARGET_SPARC64
+- case TT_WIN_OVF: /* window overflow */
+- save_window(env);
+- break;
+- case TT_WIN_UNF: /* window underflow */
+- restore_window(env);
+- break;
+- case TT_TFAULT:
+- case TT_DFAULT:
+-#if 0
+- {
+- info.si_signo = SIGSEGV;
+- info.si_errno = 0;
+- /* XXX: check env->error_code */
+- info.si_code = TARGET_SEGV_MAPERR;
+- info._sifields._sigfault._addr = env->mmuregs[4];
+- queue_signal(env, info.si_signo, &info);
+- }
+-#endif
+- break;
+-#else
+- case TT_SPILL: /* window overflow */
+- save_window(env);
+- break;
+- case TT_FILL: /* window underflow */
+- restore_window(env);
+- break;
+- case TT_TFAULT:
+- case TT_DFAULT:
+-#if 0
+- {
+- info.si_signo = SIGSEGV;
+- info.si_errno = 0;
+- /* XXX: check env->error_code */
+- info.si_code = TARGET_SEGV_MAPERR;
+- if (trapnr == TT_DFAULT)
+- info._sifields._sigfault._addr = env->dmmuregs[4];
+- else
+- info._sifields._sigfault._addr = env->tsptr->tpc;
+- //queue_signal(env, info.si_signo, &info);
+- }
+-#endif
+- break;
+-#endif
+- case EXCP_INTERRUPT:
+- /* just indicate that signals should be handled asap */
+- break;
+- case EXCP_DEBUG:
+- {
+- int sig;
+-
+- sig = gdb_handlesig(cs, TARGET_SIGTRAP);
+-#if 0
+- if (sig)
+- {
+- info.si_signo = sig;
+- info.si_errno = 0;
+- info.si_code = TARGET_TRAP_BRKPT;
+- //queue_signal(env, info.si_signo, &info);
+- }
+-#endif
+- }
+- break;
+- default:
+-#ifdef TARGET_SPARC64
+- badtrap:
+-#endif
+- printf ("Unhandled trap: 0x%x\n", trapnr);
+- cpu_dump_state(cs, stderr, fprintf, 0);
+- exit (1);
+- }
+- process_pending_signals (env);
+- }
++ target_cpu_loop(env);
+ }
+
+-#endif
+-
+ static void usage(void)
+ {
+ printf("qemu-" TARGET_NAME " version " QEMU_VERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
+@@ -709,12 +241,21 @@ static void usage(void)
+ ,
+ TARGET_NAME,
+ interp_prefix,
+- x86_stack_size);
++ target_dflssiz);
+ exit(1);
+ }
+
+ THREAD CPUState *thread_cpu;
+
++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)
+ {
+@@ -728,14 +269,54 @@ void init_task_state(TaskState *ts)
+ ts->sigqueue_table[i].next = NULL;
+ }
+
++CPUArchState *cpu_copy(CPUArchState *env)
++{
++ CPUArchState *new_env = cpu_init(cpu_model);
++#if defined(TARGET_HAS_ICE)
++ CPUBreakpoint *bp;
++ CPUWatchpoint *wp;
++#endif
++
++ /* Reset non arch specific state */
++ cpu_reset(ENV_GET_CPU(new_env));
++
++ memcpy(new_env, env, sizeof(CPUArchState));
++
++ /* Clone all break/watchpoints.
++ Note: Once we support ptrace with hw-debug register access, make sure
++ BP_CPU break/watchpoints are handled correctly on clone. */
++ QTAILQ_INIT(&env->breakpoints);
++ QTAILQ_INIT(&env->watchpoints);
++#if defined(TARGET_HAS_ICE)
++ QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
++ cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL);
++ }
++ QTAILQ_FOREACH(wp, &env->watchpoints, entry) {
++ cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1,
++ wp->flags, NULL);
++ }
++#endif
++
++ return new_env;
++}
++
++void gemu_log(const char *fmt, ...)
++{
++ va_list ap;
++
++ va_start(ap, fmt);
++ vfprintf(stderr, fmt, ap);
++ va_end(ap);
++}
++
+ int main(int argc, char **argv)
+ {
+ const char *filename;
+- const char *cpu_model;
+ const char *log_file = NULL;
+ 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;
+ CPUState *cpu;
+@@ -744,11 +325,13 @@ int main(int argc, char **argv)
+ int gdbstub_port = 0;
+ char **target_environ, **wrk;
+ envlist_t *envlist = NULL;
+- bsd_type = target_openbsd;
++ bsd_type = HOST_DEFAULT_BSD_TYPE;
+
+ if (argc <= 1)
+ usage();
+
++ save_proc_pathname(argv[0]);
++
+ module_call_init(MODULE_INIT_QOM);
+
+ if ((envlist = envlist_create()) == NULL) {
+@@ -767,7 +350,7 @@ int main(int argc, char **argv)
+ #endif
+
+ optind = 1;
+- for(;;) {
++ for (;;) {
+ if (optind >= argc)
+ break;
+ r = argv[optind];
+@@ -803,13 +386,18 @@ int main(int argc, char **argv)
+ usage();
+ } else if (!strcmp(r, "s")) {
+ r = argv[optind++];
+- x86_stack_size = strtol(r, (char **)&r, 0);
+- if (x86_stack_size <= 0)
++ target_dflssiz = strtol(r, (char **)&r, 0);
++ if (target_dflssiz <= 0) {
++ usage();
++ }
++ if (*r == 'M') {
++ target_dflssiz *= 1024 * 1024;
++ } else if (*r == 'k' || *r == 'K') {
++ target_dflssiz *= 1024;
++ }
++ if (target_dflssiz > target_maxssiz) {
+ usage();
+- if (*r == 'M')
+- x86_stack_size *= 1024 * 1024;
+- else if (*r == 'k' || *r == 'K')
+- x86_stack_size *= 1024;
++ }
+ } else if (!strcmp(r, "L")) {
+ interp_prefix = argv[optind++];
+ } else if (!strcmp(r, "p")) {
+@@ -881,6 +469,8 @@ int main(int argc, char **argv)
+ /* Zero out regs */
+ memset(regs, 0, sizeof(struct target_pt_regs));
+
++ memset(&bprm, 0, sizeof(bprm));
++
+ /* Zero out image_info */
+ memset(info, 0, sizeof(struct image_info));
+
+@@ -888,21 +478,7 @@ int main(int argc, char **argv)
+ init_paths(interp_prefix);
+
+ if (cpu_model == NULL) {
+-#if defined(TARGET_I386)
+-#ifdef TARGET_X86_64
+- cpu_model = "qemu64";
+-#else
+- cpu_model = "qemu32";
+-#endif
+-#elif defined(TARGET_SPARC)
+-#ifdef TARGET_SPARC64
+- cpu_model = "TI UltraSparc II";
+-#else
+- cpu_model = "Fujitsu MB86904";
+-#endif
+-#else
+- cpu_model = "any";
+-#endif
++ cpu_model = TARGET_DEFAULT_CPU_MODEL;
+ }
+ tcg_exec_init(0);
+ cpu_exec_init_all();
+@@ -914,9 +490,7 @@ int main(int argc, char **argv)
+ exit(1);
+ }
+ cpu = ENV_GET_CPU(env);
+-#if defined(TARGET_SPARC) || defined(TARGET_PPC)
+- cpu_reset(cpu);
+-#endif
++ TARGET_CPU_RESET(env);
+ thread_cpu = cpu;
+
+ if (getenv("QEMU_STRACE")) {
+@@ -955,7 +529,7 @@ 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)) {
+ printf("Error loading %s\n", filename);
+ _exit(1);
+ }
+@@ -1000,139 +574,10 @@ int main(int argc, char **argv)
+ memset(ts, 0, sizeof(TaskState));
+ init_task_state(ts);
+ ts->info = info;
++ ts->bprm = &bprm;
+ cpu->opaque = ts;
+
+-#if defined(TARGET_I386)
+- cpu_x86_set_cpl(env, 3);
+-
+- env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
+- env->hflags |= HF_PE_MASK;
+- if (env->features[FEAT_1_EDX] & CPUID_SSE) {
+- env->cr[4] |= CR4_OSFXSR_MASK;
+- env->hflags |= HF_OSFXSR_MASK;
+- }
+-#ifndef TARGET_ABI32
+- /* enable 64 bit mode if possible */
+- if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
+- fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
+- exit(1);
+- }
+- env->cr[4] |= CR4_PAE_MASK;
+- env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
+- env->hflags |= HF_LMA_MASK;
+-#endif
+-
+- /* flags setup : we activate the IRQs by default as in user mode */
+- env->eflags |= IF_MASK;
+-
+- /* linux register setup */
+-#ifndef TARGET_ABI32
+- env->regs[R_EAX] = regs->rax;
+- env->regs[R_EBX] = regs->rbx;
+- env->regs[R_ECX] = regs->rcx;
+- env->regs[R_EDX] = regs->rdx;
+- env->regs[R_ESI] = regs->rsi;
+- env->regs[R_EDI] = regs->rdi;
+- env->regs[R_EBP] = regs->rbp;
+- env->regs[R_ESP] = regs->rsp;
+- env->eip = regs->rip;
+-#else
+- env->regs[R_EAX] = regs->eax;
+- env->regs[R_EBX] = regs->ebx;
+- env->regs[R_ECX] = regs->ecx;
+- env->regs[R_EDX] = regs->edx;
+- env->regs[R_ESI] = regs->esi;
+- env->regs[R_EDI] = regs->edi;
+- env->regs[R_EBP] = regs->ebp;
+- env->regs[R_ESP] = regs->esp;
+- env->eip = regs->eip;
+-#endif
+-
+- /* linux interrupt setup */
+-#ifndef TARGET_ABI32
+- env->idt.limit = 511;
+-#else
+- env->idt.limit = 255;
+-#endif
+- env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
+- PROT_READ|PROT_WRITE,
+- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+- idt_table = g2h(env->idt.base);
+- set_idt(0, 0);
+- set_idt(1, 0);
+- set_idt(2, 0);
+- set_idt(3, 3);
+- set_idt(4, 3);
+- set_idt(5, 0);
+- set_idt(6, 0);
+- set_idt(7, 0);
+- set_idt(8, 0);
+- set_idt(9, 0);
+- set_idt(10, 0);
+- set_idt(11, 0);
+- set_idt(12, 0);
+- set_idt(13, 0);
+- set_idt(14, 0);
+- set_idt(15, 0);
+- set_idt(16, 0);
+- set_idt(17, 0);
+- set_idt(18, 0);
+- set_idt(19, 0);
+- set_idt(0x80, 3);
+-
+- /* linux segment setup */
+- {
+- uint64_t *gdt_table;
+- env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
+- PROT_READ|PROT_WRITE,
+- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+- env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
+- gdt_table = g2h(env->gdt.base);
+-#ifdef TARGET_ABI32
+- write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
+- DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+- (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
+-#else
+- /* 64 bit code segment */
+- write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
+- DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+- DESC_L_MASK |
+- (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
+-#endif
+- write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
+- DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
+- (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
+- }
+-
+- cpu_x86_load_seg(env, R_CS, __USER_CS);
+- cpu_x86_load_seg(env, R_SS, __USER_DS);
+-#ifdef TARGET_ABI32
+- cpu_x86_load_seg(env, R_DS, __USER_DS);
+- cpu_x86_load_seg(env, R_ES, __USER_DS);
+- cpu_x86_load_seg(env, R_FS, __USER_DS);
+- cpu_x86_load_seg(env, R_GS, __USER_DS);
+- /* This hack makes Wine work... */
+- env->segs[R_FS].selector = 0;
+-#else
+- cpu_x86_load_seg(env, R_DS, 0);
+- cpu_x86_load_seg(env, R_ES, 0);
+- cpu_x86_load_seg(env, R_FS, 0);
+- cpu_x86_load_seg(env, R_GS, 0);
+-#endif
+-#elif defined(TARGET_SPARC)
+- {
+- int i;
+- env->pc = regs->pc;
+- env->npc = regs->npc;
+- env->y = regs->y;
+- for(i = 0; i < 8; i++)
+- env->gregs[i] = regs->u_regs[i];
+- for(i = 0; i < 8; i++)
+- env->regwptr[i] = regs->u_regs[i + 8];
+- }
+-#else
+-#error unsupported target CPU
+-#endif
++ target_cpu_init(env, regs);
+
+ if (gdbstub_port) {
+ gdbserver_start (gdbstub_port);
+diff --git a/bsd-user/mips/syscall.h b/bsd-user/mips/syscall.h
+new file mode 100644
+index 0000000..aacc6dd
+--- /dev/null
++++ b/bsd-user/mips/syscall.h
+@@ -0,0 +1,52 @@
++/*
++ * mips system call definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _MIPS_SYSCALL_H_
++#define _MIPS_SYSCALL_H_
++
++/*
++ * struct target_pt_regs 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;
++};
++
++#if defined(TARGET_WORDS_BIGENDIAN)
++#define UNAME_MACHINE "mips"
++#else
++#define UNAME_MACHINE "mipsel"
++#endif
++
++#define TARGET_HW_MACHINE "mips"
++#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE
++
++/* sysarch() commands */
++#define TARGET_MIPS_SET_TLS 1
++#define TARGET_MIPS_GET_TLS 2
++
++#endif /* !_MIPS_SYSCALL_H_ */
+diff --git a/bsd-user/mips/target_arch.h b/bsd-user/mips/target_arch.h
+new file mode 100644
+index 0000000..b3d32ba
+--- /dev/null
++++ b/bsd-user/mips/target_arch.h
+@@ -0,0 +1,10 @@
++
++#ifndef _TARGET_ARCH_H_
++#define _TARGET_ARCH_H_
++
++#include "qemu.h"
++
++void target_cpu_set_tls(CPUMIPSState *env, target_ulong newtls);
++target_ulong target_cpu_get_tls(CPUMIPSState *env);
++
++#endif /* !_TARGET_ARCH_H_ */
+diff --git a/bsd-user/mips/target_arch_cpu.c b/bsd-user/mips/target_arch_cpu.c
+new file mode 100644
+index 0000000..dd59435
+--- /dev/null
++++ b/bsd-user/mips/target_arch_cpu.c
+@@ -0,0 +1,27 @@
++/*
++ * mips cpu related code
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#include "target_arch.h"
++
++void target_cpu_set_tls(CPUMIPSState *env, target_ulong newtls)
++{
++ env->tls_value = newtls;
++}
++
++target_ulong target_cpu_get_tls(CPUMIPSState *env)
++{
++ return (env->tls_value);
++}
+diff --git a/bsd-user/mips/target_arch_cpu.h b/bsd-user/mips/target_arch_cpu.h
+new file mode 100644
+index 0000000..5098b7d
+--- /dev/null
++++ b/bsd-user/mips/target_arch_cpu.h
+@@ -0,0 +1,257 @@
++/*
++ * mips cpu init and loop
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _TARGET_ARCH_CPU_H_
++#define _TARGET_ARCH_CPU_H_
++
++#include "target_arch.h"
++
++#if defined(TARGET_ABI_MIPSN32)
++# define TARGET_DEFAULT_CPU_MODEL "24Kc"
++#else
++# define TARGET_DEFAULT_CPU_MODEL "24Kf"
++#endif
++
++#define TARGET_CPU_RESET(env)
++
++static inline void target_cpu_init(CPUMIPSState *env,
++ struct target_pt_regs *regs)
++{
++ 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;
++ }
++}
++
++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;
++}
++
++static inline void target_cpu_loop(CPUMIPSState *env)
++{
++ CPUState *cs = CPU(mips_env_get_cpu(env));
++ target_siginfo_t info;
++ int trapnr;
++ abi_long ret;
++ unsigned int syscall_num;
++
++ for (;;) {
++ cpu_exec_start(cs);
++ trapnr = cpu_mips_exec(env);
++ cpu_exec_end(cs);
++ switch (trapnr) {
++ case EXCP_SYSCALL: /* syscall exception */
++ if (bsd_type == target_freebsd) {
++ syscall_num = env->active_tc.gpr[2]; /* v0 */
++ env->active_tc.PC += TARGET_INSN_SIZE;
++ if (syscall_num >= TARGET_FREEBSD_NR_MAXSYSCALL) {
++ ret = -TARGET_ENOSYS;
++ } else {
++ abi_ulong arg4 = 0, arg5 = 0, arg6 = 0, arg7 =0;
++ abi_ulong sp_reg = env->active_tc.gpr[29];
++
++# ifdef TARGET_ABI_MIPSO32
++ get_user_ual(arg4, sp_reg + 16);
++ get_user_ual(arg5, sp_reg + 20);
++ get_user_ual(arg6, sp_reg + 24);
++ get_user_ual(arg7, sp_reg + 28);
++#else
++ arg4 = env->active_tc.gpr[12]; /* t4/arg4 */
++ arg5 = env->active_tc.gpr[13]; /* t5/arg5 */
++ arg6 = env->active_tc.gpr[14]; /* t6/arg6 */
++ arg7 = env->active_tc.gpr[15]; /* t7/arg7 */
++#endif
++ /* mips(32) uses regs 4-7,12-15 for args */
++ if (TARGET_FREEBSD_NR___syscall == syscall_num ||
++ TARGET_FREEBSD_NR_syscall == syscall_num) {
++ /* 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 */
++ arg4,
++ arg5,
++ arg6,
++ arg7,
++ 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 */
++ arg4,
++ arg5,
++ arg6,
++ arg7
++ );
++ }
++ }
++ /* Compare to mips/mips/vm_machdep.c cpu_set_syscall_retval() */
++ if (-TARGET_EJUSTRETURN == ret) {
++ /*
++ * Returning from a successful sigreturn
++ * syscall. Avoid clobbering register state.
++ */
++ break;
++ }
++ if (-TARGET_ERESTART == ret) {
++ /* Backup the pc to point at the swi. */
++ env->active_tc.PC -= TARGET_INSN_SIZE;
++ 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 */
++ } /* else if (bsd_type == target_openbsd)... */
++ else {
++ fprintf(stderr, "qemu: bsd_type (= %d) syscall not supported\n",
++ bsd_type);
++ }
++ 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.target_si_signo = TARGET_SIGSEGV;
++ info.target_si_errno = 0;
++ /* XXX: check env->error_code */
++ info.target_si_code = TARGET_SEGV_MAPERR;
++ info.target_si_addr = env->CP0_BadVAddr;
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP_CpU: /* coprocessor unusable */
++ case EXCP_RI: /* reserved instruction */
++ info.target_si_signo = TARGET_SIGILL;
++ info.target_si_errno = 0;
++ info.target_si_code = 0;
++ queue_signal(env, info.target_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(cs, TARGET_SIGTRAP);
++ if (sig) {
++ info.target_si_signo = sig;
++ info.target_si_errno = 0;
++ info.target_si_code = TARGET_TRAP_BRKPT;
++ queue_signal(env, info.target_si_signo, &info);
++ }
++ }
++ break;
++
++ case EXCP_SC:
++ if (do_store_exclusive(env)) {
++ info.target_si_signo = TARGET_SIGSEGV;
++ info.target_si_errno = 0;
++ info.target_si_code = TARGET_SEGV_MAPERR;
++ info.target_si_addr = env->active_tc.PC;
++ queue_signal(env, info.target_si_signo, &info);
++ }
++ break;
++
++ default:
++ fprintf(stderr, "qemu: unhandled CPU exception "
++ "0x%x - aborting\n", trapnr);
++ cpu_dump_state(cs, stderr, fprintf, 0);
++ abort();
++ }
++ process_pending_signals(env);
++ }
++}
++
++static inline void target_cpu_clone_regs(CPUMIPSState *env, target_ulong newsp)
++{
++ if (newsp)
++ env->active_tc.gpr[29] = newsp;
++ env->active_tc.gpr[7] = 0;
++ env->active_tc.gpr[2] = 0;
++}
++
++static inline void target_cpu_reset(CPUArchState *cpu)
++{
++}
++
++#endif /* ! _TARGET_ARCH_CPU_H_ */
+diff --git a/bsd-user/mips/target_arch_elf.h b/bsd-user/mips/target_arch_elf.h
+new file mode 100644
+index 0000000..8630f34
+--- /dev/null
++++ b/bsd-user/mips/target_arch_elf.h
+@@ -0,0 +1,36 @@
++/*
++ * mips ELF definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_ELF_H_
++#define _TARGET_ARCH_ELF_H_
++
++#define elf_check_arch(x) ( (x) == EM_MIPS )
++#define ELF_START_MMAP 0x80000000
++#define ELF_CLASS ELFCLASS32
++
++#ifdef TARGET_WORDS_BIGENDIAN
++#define ELF_DATA ELFDATA2MSB
++#else
++#define ELF_DATA ELFDATA2LSB
++#endif
++#define ELF_ARCH EM_MIPS
++
++#define USE_ELF_CORE_DUMP
++#define ELF_EXEC_PAGESIZE 4096
++
++#endif /* _TARGET_ARCH_ELF_H_ */
+diff --git a/bsd-user/mips/target_arch_signal.h b/bsd-user/mips/target_arch_signal.h
+new file mode 100644
+index 0000000..79d6f65
+--- /dev/null
++++ b/bsd-user/mips/target_arch_signal.h
+@@ -0,0 +1,237 @@
++/*
++ * mips signal definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_SIGNAL_H_
++#define _TARGET_ARCH_SIGNAL_H_
++
++#include "cpu.h"
++
++#define TARGET_INSN_SIZE 4 /* mips instruction size */
++
++/* Size of the signal trampolin code. See insall_sigtramp(). */
++#define TARGET_SZSIGCODE ((abi_ulong)(4 * TARGET_INSN_SIZE))
++
++/* compare to mips/include/_limits.h */
++#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) /* recommended size */
++
++/* compare to sys/mips/include/asm.h */
++#define TARGET_SZREG 8
++#define TARGET_CALLFRAME_SIZ (TARGET_SZREG * 4)
++
++/* mips/mips/pm_machdep.c */
++#define TARGET_UCONTEXT_MAGIC 0xACEDBADE
++#define TARGET_MC_GET_CLEAR_RET 0x0001
++#define TARGET_MC_ADD_MAGIC 0x0002
++#define TARGET_MC_SET_ONSTACK 0x0004
++
++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];
++};
++
++/*
++ * Compare to mips/mips/pm_machdep.c sendsig()
++ * Assumes that target stack frame memory is locked.
++ */
++static inline abi_long
++set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
++ abi_ulong frame_addr, struct target_sigaction *ka)
++{
++
++ /* frame->sf_si.si_addr = regs->CP0_BadVAddr; */
++
++ /* MIPS only struct target_sigframe members: */
++ frame->sf_signum = sig;
++ frame->sf_siginfo = frame_addr + offsetof(struct target_sigframe, sf_si);
++ frame->sf_ucontext = frame_addr + offsetof(struct target_sigframe, sf_uc);
++
++ /*
++ * 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;
++
++ 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 abi_long 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 abi_long set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp,
++ int srflag)
++{
++ 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);
++
++ 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;
++}
++
++static inline abi_long get_ucontext_sigreturn(CPUMIPSState *regs,
++ abi_ulong target_sf, abi_ulong *target_uc)
++{
++
++ *target_uc = target_sf;
++ return 0;
++}
++
++
++#endif /* !_TARGET_ARCH_SIGNAL_H_ */
+diff --git a/bsd-user/mips/target_arch_sigtramp.h b/bsd-user/mips/target_arch_sigtramp.h
+new file mode 100644
+index 0000000..5e3c69a
+--- /dev/null
++++ b/bsd-user/mips/target_arch_sigtramp.h
+@@ -0,0 +1,23 @@
++
++#ifndef _TARGET_ARCH_SIGTRAMP_H_
++#define _TARGET_ARCH_SIGTRAMP_H_
++
++/* Compare to mips/mips/locore.S sigcode() */
++static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
++ unsigned sys_sigreturn)
++{
++ int i;
++ uint32_t sigtramp_code[TARGET_SZSIGCODE/TARGET_INSN_SIZE] = {
++ /* 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);
++}
++#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
+diff --git a/bsd-user/mips/target_arch_sysarch.h b/bsd-user/mips/target_arch_sysarch.h
+new file mode 100644
+index 0000000..d333740
+--- /dev/null
++++ b/bsd-user/mips/target_arch_sysarch.h
+@@ -0,0 +1,69 @@
++/*
++ * mips sysarch() system call emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __ARCH_SYSARCH_H_
++#define __ARCH_SYSARCH_H_
++
++#include "syscall.h"
++#include "target_arch.h"
++
++static inline abi_long do_freebsd_arch_sysarch(CPUMIPSState *env, int op,
++ abi_ulong parms)
++{
++ int ret = 0;
++
++ switch (op) {
++ case TARGET_MIPS_SET_TLS:
++ target_cpu_set_tls(env, parms);
++ break;
++
++ case TARGET_MIPS_GET_TLS:
++ if (put_user(target_cpu_get_tls(env), parms, abi_ulong)) {
++ ret = -TARGET_EFAULT;
++ }
++ break;
++
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++
++ return ret;
++}
++
++static inline void do_freebsd_arch_print_sysarch(
++ const struct syscallname *name, abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
++{
++
++ switch (arg1) {
++ case TARGET_MIPS_SET_TLS:
++ gemu_log("%s(SET_TLS, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2);
++ break;
++
++ case TARGET_MIPS_GET_TLS:
++ 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);
++ }
++}
++
++#endif /*!__ARCH_SYSARCH_H_ */
+diff --git a/bsd-user/mips/target_arch_thread.h b/bsd-user/mips/target_arch_thread.h
+new file mode 100644
+index 0000000..c76b0d6
+--- /dev/null
++++ b/bsd-user/mips/target_arch_thread.h
+@@ -0,0 +1,54 @@
++/*
++ * mips thread support
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_THREAD_H_
++#define _TARGET_ARCH_THREAD_H_
++
++/* Compare to mips/mips/vm_machdep.c cpu_set_upcall_kse() */
++static inline void target_thread_set_upcall(CPUMIPSState *regs, abi_ulong entry,
++ abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
++{
++ abi_ulong sp;
++
++ /*
++ * At the point where a function is called, sp must be 8
++ * byte aligned[for compatibility with 64-bit CPUs]
++ * in ``See MIPS Run'' by D. Sweetman, p. 269
++ * align stack
++ */
++ sp = ((stack_base + stack_size) & ~0x7) - TARGET_CALLFRAME_SIZ;
++
++ /* t9 = pc = start function entry */
++ regs->active_tc.gpr[25] = regs->active_tc.PC = entry;
++ /* a0 = arg */
++ regs->active_tc.gpr[4] = arg;
++ /* sp = top of the stack */
++ regs->active_tc.gpr[29] = sp;
++}
++
++static inline void target_thread_init(struct target_pt_regs *regs,
++ struct image_info *infop)
++{
++ regs->cp0_status = 2 << CP0St_KSU;
++ regs->regs[25] = regs->cp0_epc = infop->entry & ~3; /* t9/pc = entry */
++ regs->regs[4] = regs->regs[29] = infop->start_stack; /* a0/sp = stack */
++ regs->regs[5] = regs->regs[6] = 0; /* a1/a2 = 0 */
++ regs->regs[7] = TARGET_PS_STRINGS; /* a3 = ps_strings */
++}
++
++#endif /* !_TARGET_ARCH_THREAD_H_ */
+diff --git a/bsd-user/mips/target_arch_vmparam.h b/bsd-user/mips/target_arch_vmparam.h
+new file mode 100644
+index 0000000..695877a
+--- /dev/null
++++ b/bsd-user/mips/target_arch_vmparam.h
+@@ -0,0 +1,50 @@
++/*
++ * mips VM parameters definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_VMPARAM_H_
++#define _TARGET_ARCH_VMPARAM_H_
++
++#include "cpu.h"
++
++/* compare to sys/mips/include/vmparam.h */
++#define TARGET_MAXTSIZ (128UL*1024*1024) /* max text size */
++#define TARGET_DFLDSIZ (128UL*1024*1024) /* initial data size limit */
++#define TARGET_MAXDSIZ (1*1024UL*1024*1024) /* max data size */
++#define TARGET_DFLSSIZ (8UL*1024*1024) /* initial stack size limit */
++#define TARGET_MAXSSIZ (64UL*1024*1024) /* max stack size */
++#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */
++
++/* MIPS only supports 31 bits of virtual address space for user space */
++#define TARGET_RESERVED_VA 0x77000000
++
++#define TARGET_VM_MINUSER_ADDRESS (0x00000000)
++#define TARGET_VM_MAXUSER_ADDRESS (0x80000000)
++
++#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
++
++static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
++{
++ return state->active_tc.gpr[29];
++}
++
++static inline void set_second_rval(CPUMIPSState *state, abi_ulong retval2)
++{
++ state->active_tc.gpr[3] = retval2;
++}
++
++#endif /* ! _TARGET_ARCH_VMPARAM_H_ */
+diff --git a/bsd-user/mips64/syscall.h b/bsd-user/mips64/syscall.h
+new file mode 100644
+index 0000000..bf4c598
+--- /dev/null
++++ b/bsd-user/mips64/syscall.h
+@@ -0,0 +1,53 @@
++/*
++ * mips64 system call definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _MIPS64_SYSCALL_H_
++#define _MIPS64_SYSCALL_H_
++
++/*
++ * struct target_pt_regs 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;
++};
++
++
++#if defined(TARGET_WORDS_BIGENDIAN)
++#define UNAME_MACHINE "mips64"
++#else
++#define UNAME_MACHINE "mips64el"
++#endif
++
++#define TARGET_HW_MACHINE "mips"
++#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE
++
++/* sysarch() commands */
++#define TARGET_MIPS_SET_TLS 1
++#define TARGET_MIPS_GET_TLS 2
++
++#endif /* !_MIPS64_SYSCALL_H_ */
+diff --git a/bsd-user/mips64/target_arch.h b/bsd-user/mips64/target_arch.h
+new file mode 100644
+index 0000000..b3d32ba
+--- /dev/null
++++ b/bsd-user/mips64/target_arch.h
+@@ -0,0 +1,10 @@
++
++#ifndef _TARGET_ARCH_H_
++#define _TARGET_ARCH_H_
++
++#include "qemu.h"
++
++void target_cpu_set_tls(CPUMIPSState *env, target_ulong newtls);
++target_ulong target_cpu_get_tls(CPUMIPSState *env);
++
++#endif /* !_TARGET_ARCH_H_ */
+diff --git a/bsd-user/mips64/target_arch_cpu.c b/bsd-user/mips64/target_arch_cpu.c
+new file mode 100644
+index 0000000..9d016a3
+--- /dev/null
++++ b/bsd-user/mips64/target_arch_cpu.c
+@@ -0,0 +1,27 @@
++/*
++ * mips64 cpu related code
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#include "target_arch.h"
++
++void target_cpu_set_tls(CPUMIPSState *env, target_ulong newtls)
++{
++ env->tls_value = newtls;
++}
++
++target_ulong target_cpu_get_tls(CPUMIPSState *env)
++{
++ return (env->tls_value);
++}
+diff --git a/bsd-user/mips64/target_arch_cpu.h b/bsd-user/mips64/target_arch_cpu.h
+new file mode 100644
+index 0000000..f4e212f
+--- /dev/null
++++ b/bsd-user/mips64/target_arch_cpu.h
+@@ -0,0 +1,243 @@
++/*
++ * mips64 cpu init and loop
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _TARGET_ARCH_CPU_H_
++#define _TARGET_ARCH_CPU_H_
++
++#include "target_arch.h"
++
++#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64)
++# define TARGET_DEFAULT_CPU_MODEL "MIPS64R2-generic"
++#else
++# define TARGET_DEFAULT_CPU_MODEL "24f"
++#endif
++
++#define TARGET_CPU_RESET(env)
++
++static inline void target_cpu_init(CPUMIPSState *env,
++ struct target_pt_regs *regs)
++{
++ 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;
++ }
++ env->hflags |= MIPS_HFLAG_UX | MIPS_HFLAG_64;
++}
++
++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;
++}
++
++static inline void target_cpu_loop(CPUMIPSState *env)
++{
++ CPUState *cs = CPU(mips_env_get_cpu(env));
++ target_siginfo_t info;
++ int trapnr;
++ abi_long ret;
++ unsigned int syscall_num;
++
++ for (;;) {
++ cpu_exec_start(cs);
++ trapnr = cpu_mips_exec(env);
++ cpu_exec_end(cs);
++ switch (trapnr) {
++ case EXCP_SYSCALL: /* syscall exception */
++ if (bsd_type == target_freebsd) {
++ syscall_num = env->active_tc.gpr[2]; /* v0 */
++ env->active_tc.PC += TARGET_INSN_SIZE;
++ if (syscall_num >= TARGET_FREEBSD_NR_MAXSYSCALL) {
++ ret = -TARGET_ENOSYS;
++ } else {
++ /* mips64 uses regs 4-11 for args */
++ if (TARGET_FREEBSD_NR___syscall == syscall_num ||
++ TARGET_FREEBSD_NR_syscall == syscall_num) {
++ /* indirect syscall */
++ 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 {
++ /* direct syscall */
++ 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]
++ );
++ }
++ }
++ /* Compare to mips/mips/vm_machdep.c cpu_set_syscall_retval() */
++ if (-TARGET_EJUSTRETURN == ret) {
++ /*
++ * Returning from a successful sigreturn
++ * syscall. Avoid clobbering register state.
++ */
++ break;
++ }
++ if (-TARGET_ERESTART == ret) {
++ /* Backup the pc to point at the swi. */
++ env->active_tc.PC -= TARGET_INSN_SIZE;
++ 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 */
++ } /* else if (bsd_type == target_openbsd)... */
++ else {
++ fprintf(stderr, "qemu: bsd_type (= %d) syscall not supported\n",
++ bsd_type);
++ }
++ 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.target_si_signo = TARGET_SIGSEGV;
++ info.target_si_errno = 0;
++ /* XXX: check env->error_code */
++ info.target_si_code = TARGET_SEGV_MAPERR;
++ info.target_si_addr = env->CP0_BadVAddr;
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP_CpU: /* coprocessor unusable */
++ case EXCP_RI: /* reserved instruction */
++ info.target_si_signo = TARGET_SIGILL;
++ info.target_si_errno = 0;
++ info.target_si_code = 0;
++ queue_signal(env, info.target_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(cs, TARGET_SIGTRAP);
++ if (sig) {
++ info.target_si_signo = sig;
++ info.target_si_errno = 0;
++ info.target_si_code = TARGET_TRAP_BRKPT;
++ queue_signal(env, info.target_si_signo, &info);
++ }
++ }
++ break;
++
++ case EXCP_SC:
++ if (do_store_exclusive(env)) {
++ info.target_si_signo = TARGET_SIGSEGV;
++ info.target_si_errno = 0;
++ info.target_si_code = TARGET_SEGV_MAPERR;
++ info.target_si_addr = env->active_tc.PC;
++ queue_signal(env, info.target_si_signo, &info);
++ }
++ break;
++
++ default:
++ fprintf(stderr, "qemu: unhandled CPU exception "
++ "0x%x - aborting\n", trapnr);
++ cpu_dump_state(cs, stderr, fprintf, 0);
++ abort();
++ }
++ process_pending_signals(env);
++ }
++}
++
++static inline void target_cpu_clone_regs(CPUMIPSState *env, target_ulong newsp)
++{
++ if (newsp)
++ env->active_tc.gpr[29] = newsp;
++ env->active_tc.gpr[7] = 0;
++ env->active_tc.gpr[2] = 0;
++}
++
++static inline void target_cpu_reset(CPUArchState *cpu)
++{
++}
++
++#endif /* ! _TARGET_ARCH_CPU_H_ */
+diff --git a/bsd-user/mips64/target_arch_elf.h b/bsd-user/mips64/target_arch_elf.h
+new file mode 100644
+index 0000000..ca0da03
+--- /dev/null
++++ b/bsd-user/mips64/target_arch_elf.h
+@@ -0,0 +1,36 @@
++/*
++ * mips64 ELF definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_ELF_H_
++#define _TARGET_ARCH_ELF_H_
++
++#define elf_check_arch(x) ( (x) == EM_MIPS )
++#define ELF_START_MMAP 0x2aaaaab000ULL
++#define ELF_CLASS ELFCLASS64
++
++#ifdef TARGET_WORDS_BIGENDIAN
++#define ELF_DATA ELFDATA2MSB
++#else
++#define ELF_DATA ELFDATA2LSB
++#endif
++#define ELF_ARCH EM_MIPS
++
++#define USE_ELF_CORE_DUMP
++#define ELF_EXEC_PAGESIZE 4096
++
++#endif /* _TARGET_ARCH_ELF_H_ */
+diff --git a/bsd-user/mips64/target_arch_signal.h b/bsd-user/mips64/target_arch_signal.h
+new file mode 100644
+index 0000000..2f79a24
+--- /dev/null
++++ b/bsd-user/mips64/target_arch_signal.h
+@@ -0,0 +1,214 @@
++/*
++ * mips64 signal definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_SIGNAL_H_
++#define _TARGET_ARCH_SIGNAL_H_
++
++#include "cpu.h"
++
++#define TARGET_INSN_SIZE 4 /* mips64 instruction size */
++
++/* Size of the signal trampolin code placed on the stack. */
++#define TARGET_SZSIGCODE ((abi_ulong)(4 * TARGET_INSN_SIZE))
++
++#define TARGET_MINSIGSTKSZ (512 * 4)
++#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
++
++/* compare to sys/mips/include/asm.h */
++#define TARGET_SZREG 8
++#define TARGET_CALLFRAME_SIZ (TARGET_SZREG * 4)
++
++/* mips/mips/pm_machdep.c */
++#define TARGET_UCONTEXT_MAGIC 0xACEDBADE
++#define TARGET_MC_GET_CLEAR_RET 0x0001
++#define TARGET_MC_ADD_MAGIC 0x0002
++#define TARGET_MC_SET_ONSTACK 0x0004
++
++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];
++};
++
++/*
++ * Compare to mips/mips/pm_machdep.c sendsig()
++ * Assumes that target stack frame memory is locked.
++ */
++static inline abi_long
++set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
++ abi_ulong frame_addr, struct target_sigaction *ka)
++{
++
++ /* frame->sf_si.si_addr = regs->CP0_BadVAddr; */
++
++ /* MIPS only struct target_sigframe members: */
++ frame->sf_signum = sig;
++ frame->sf_siginfo = frame_addr + offsetof(struct target_sigframe, sf_si);
++ frame->sf_ucontext = frame_addr + offsetof(struct target_sigframe, sf_uc);
++
++ /*
++ * 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;
++
++ 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 abi_long 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]);
++ }
++
++ mcp->mc_fpused = 1;
++ for (i = 0; i < 32; i++) {
++ mcp->mc_fpregs[i] = tswapal(regs->active_fpu.fpr[i].d);
++ }
++ mcp->mc_fpregs[32] = tswapal(regs->active_fpu.fcr0);
++ mcp->mc_fpc_eir = tswapal(regs->active_fpu.fcr31);
++
++ 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 abi_long set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp,
++ int srflag)
++{
++ int i, err = 0;
++
++ for (i = 1; i < 32; i++) {
++ regs->active_tc.gpr[i] = tswapal(mcp->mc_regs[i]);
++ }
++
++ if (mcp->mc_fpused) {
++ /* restore fpu context if we have used it before */
++ for (i = 0; i < 32; i++) {
++ regs->active_fpu.fpr[i].d = tswapal(mcp->mc_fpregs[i]);
++ }
++ regs->active_fpu.fcr0 = tswapal(mcp->mc_fpregs[32]);
++ regs->active_fpu.fcr31 = tswapal(mcp->mc_fpc_eir);
++ }
++
++ 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);
++
++ 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;
++}
++
++static inline abi_long get_ucontext_sigreturn(CPUMIPSState *regs,
++ abi_ulong target_sf, abi_ulong *target_uc)
++{
++
++ /* mips passes ucontext struct as the stack frame */
++ *target_uc = target_sf;
++ return 0;
++}
++
++#endif /* !_TARGET_ARCH_SIGNAL_H_ */
+diff --git a/bsd-user/mips64/target_arch_sigtramp.h b/bsd-user/mips64/target_arch_sigtramp.h
+new file mode 100644
+index 0000000..5e3c69a
+--- /dev/null
++++ b/bsd-user/mips64/target_arch_sigtramp.h
+@@ -0,0 +1,23 @@
++
++#ifndef _TARGET_ARCH_SIGTRAMP_H_
++#define _TARGET_ARCH_SIGTRAMP_H_
++
++/* Compare to mips/mips/locore.S sigcode() */
++static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
++ unsigned sys_sigreturn)
++{
++ int i;
++ uint32_t sigtramp_code[TARGET_SZSIGCODE/TARGET_INSN_SIZE] = {
++ /* 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);
++}
++#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
+diff --git a/bsd-user/mips64/target_arch_sysarch.h b/bsd-user/mips64/target_arch_sysarch.h
+new file mode 100644
+index 0000000..95b4e78
+--- /dev/null
++++ b/bsd-user/mips64/target_arch_sysarch.h
+@@ -0,0 +1,69 @@
++/*
++ * mips64 sysarch() system call emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __ARCH_SYSARCH_H_
++#define __ARCH_SYSARCH_H_
++
++#include "syscall.h"
++#include "target_arch.h"
++
++static inline abi_long do_freebsd_arch_sysarch(CPUMIPSState *env, int op,
++ abi_ulong parms)
++{
++ int ret = 0;
++
++ switch (op) {
++ case TARGET_MIPS_SET_TLS:
++ target_cpu_set_tls(env, parms);
++ break;
++
++ case TARGET_MIPS_GET_TLS:
++ if (put_user(target_cpu_get_tls(env), parms, abi_ulong)) {
++ ret = -TARGET_EFAULT;
++ }
++ break;
++
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++
++ return ret;
++}
++
++static inline void do_freebsd_arch_print_sysarch(
++ const struct syscallname *name, abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
++{
++
++ switch (arg1) {
++ case TARGET_MIPS_SET_TLS:
++ gemu_log("%s(SET_TLS, 0x" TARGET_ABI_FMT_lx ")", name->name, arg2);
++ break;
++
++ case TARGET_MIPS_GET_TLS:
++ 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);
++ }
++}
++
++#endif /*!__ARCH_SYSARCH_H_ */
+diff --git a/bsd-user/mips64/target_arch_thread.h b/bsd-user/mips64/target_arch_thread.h
+new file mode 100644
+index 0000000..7fcd866
+--- /dev/null
++++ b/bsd-user/mips64/target_arch_thread.h
+@@ -0,0 +1,54 @@
++/*
++ * mips64 thread support
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _MIPS64_ARCH_THREAD_H_
++#define _MIPS64_ARCH_THREAD_H_
++
++/* Compare to mips/mips/vm_machdep.c cpu_set_upcall_kse() */
++static inline void target_thread_set_upcall(CPUMIPSState *regs, abi_ulong entry,
++ abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
++{
++ abi_ulong sp;
++
++ /*
++ * At the point where a function is called, sp must be 8
++ * byte aligned[for compatibility with 64-bit CPUs]
++ * in ``See MIPS Run'' by D. Sweetman, p. 269
++ * align stack
++ */
++ sp = ((stack_base + stack_size) & ~0x7) - TARGET_CALLFRAME_SIZ;
++
++ /* t9 = pc = start function entry */
++ regs->active_tc.gpr[25] = regs->active_tc.PC = entry;
++ /* a0 = arg */
++ regs->active_tc.gpr[4] = arg;
++ /* sp = top of the stack */
++ regs->active_tc.gpr[29] = sp;
++}
++
++static inline void target_thread_init(struct target_pt_regs *regs,
++ struct image_info *infop)
++{
++ regs->cp0_status = 2 << CP0St_KSU;
++ regs->regs[25] = regs->cp0_epc = infop->entry & ~3; /* t9/pc = entry */
++ regs->regs[4] = regs->regs[29] = infop->start_stack; /* a0/sp = stack */
++ regs->regs[5] = regs->regs[6] = 0; /* a1/a2 = 0 */
++ regs->regs[7] = TARGET_PS_STRINGS; /* a3 = ps_strings */
++}
++
++#endif /* !_MIPS64_ARCH_THREAD_H_ */
+diff --git a/bsd-user/mips64/target_arch_vmparam.h b/bsd-user/mips64/target_arch_vmparam.h
+new file mode 100644
+index 0000000..1ba09e0
+--- /dev/null
++++ b/bsd-user/mips64/target_arch_vmparam.h
+@@ -0,0 +1,47 @@
++/*
++ * mips64 VM parameters definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_VMPARAM_H_
++#define _TARGET_ARCH_VMPARAM_H_
++
++#include "cpu.h"
++
++/* compare to sys/mips/include/vmparam.h */
++#define TARGET_MAXTSIZ (128UL*1024*1024) /* max text size */
++#define TARGET_DFLDSIZ (128UL*1024*1024) /* initial data size limit */
++#define TARGET_MAXDSIZ (1*1024UL*1024*1024) /* max data size */
++#define TARGET_DFLSSIZ (8UL*1024*1024) /* initial stack size limit */
++#define TARGET_MAXSSIZ (64UL*1024*1024) /* max stack size */
++#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */
++
++#define TARGET_VM_MINUSER_ADDRESS (0x0000000000000000UL)
++#define TARGET_VM_MAXUSER_ADDRESS (0x0000008000000000UL)
++
++#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
++
++static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state)
++{
++ return state->active_tc.gpr[29];
++}
++
++static inline void set_second_rval(CPUMIPSState *state, abi_ulong retval2)
++{
++ state->active_tc.gpr[3] = retval2;
++}
++
++#endif /* ! _TARGET_ARCH_VMPARAM_H_ */
+diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
+index aae8ea1..96a09f3 100644
+--- a/bsd-user/mmap.c
++++ b/bsd-user/mmap.c
+@@ -1,4 +1,4 @@
+-/*
++/**
+ * mmap support for qemu
+ *
+ * Copyright (c) 2003 - 2008 Fabrice Bellard
+@@ -26,13 +26,11 @@
+
+ #include "qemu.h"
+ #include "qemu-common.h"
+-#include "bsd-mman.h"
+
+-//#define DEBUG_MMAP
++// #define DEBUG_MMAP
+
+-#if defined(CONFIG_USE_NPTL)
+-pthread_mutex_t mmap_mutex;
+-static int __thread mmap_lock_count;
++pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
++static __thread int mmap_lock_count;
+
+ void mmap_lock(void)
+ {
+@@ -63,76 +61,6 @@ void mmap_fork_end(int child)
+ else
+ pthread_mutex_unlock(&mmap_mutex);
+ }
+-#else
+-/* We aren't threadsafe to start with, so no need to worry about locking. */
+-void mmap_lock(void)
+-{
+-}
+-
+-void mmap_unlock(void)
+-{
+-}
+-#endif
+-
+-static void *bsd_vmalloc(size_t size)
+-{
+- void *p;
+- mmap_lock();
+- /* Use map and mark the pages as used. */
+- p = mmap(NULL, size, PROT_READ | PROT_WRITE,
+- MAP_PRIVATE | MAP_ANON, -1, 0);
+-
+- if (h2g_valid(p)) {
+- /* Allocated region overlaps guest address space.
+- This may recurse. */
+- abi_ulong addr = h2g(p);
+- page_set_flags(addr & TARGET_PAGE_MASK, TARGET_PAGE_ALIGN(addr + size),
+- PAGE_RESERVED);
+- }
+-
+- mmap_unlock();
+- return p;
+-}
+-
+-void *g_malloc(size_t size)
+-{
+- char * p;
+- size += 16;
+- p = bsd_vmalloc(size);
+- *(size_t *)p = size;
+- return p + 16;
+-}
+-
+-/* We use map, which is always zero initialized. */
+-void * g_malloc0(size_t size)
+-{
+- return g_malloc(size);
+-}
+-
+-void g_free(void *ptr)
+-{
+- /* FIXME: We should unmark the reserved pages here. However this gets
+- complicated when one target page spans multiple host pages, so we
+- don't bother. */
+- size_t *p;
+- p = (size_t *)((char *)ptr - 16);
+- munmap(p, *p);
+-}
+-
+-void *g_realloc(void *ptr, size_t size)
+-{
+- size_t old_size, copy;
+- void *new_ptr;
+-
+- if (!ptr)
+- return g_malloc(size);
+- old_size = *(size_t *)((char *)ptr - 16);
+- copy = old_size < size ? old_size : size;
+- new_ptr = g_malloc(size);
+- memcpy(new_ptr, ptr, copy);
+- g_free(ptr);
+- return new_ptr;
+-}
+
+ /* NOTE: all the constants are the HOST ones, but addresses are target. */
+ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
+@@ -164,11 +92,11 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
+ if (start > host_start) {
+ /* handle host page containing start */
+ prot1 = prot;
+- for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
++ for (addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
+ prot1 |= page_get_flags(addr);
+ }
+ if (host_end == host_start + qemu_host_page_size) {
+- for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
++ for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+ prot1 |= page_get_flags(addr);
+ }
+ end = host_end;
+@@ -180,7 +108,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
+ }
+ if (end < host_end) {
+ prot1 = prot;
+- for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
++ for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
+ prot1 |= page_get_flags(addr);
+ }
+ ret = mprotect(g2h(host_end - qemu_host_page_size), qemu_host_page_size,
+@@ -218,7 +146,7 @@ static int mmap_frag(abi_ulong real_start,
+
+ /* get the protection of the target pages outside the mapping */
+ prot1 = 0;
+- for(addr = real_start; addr < real_end; addr++) {
++ for (addr = real_start; addr < real_end; addr++) {
+ if (addr < start || addr >= end)
+ prot1 |= page_get_flags(addr);
+ }
+@@ -238,15 +166,19 @@ static int mmap_frag(abi_ulong real_start,
+ /* msync() won't work here, so we return an error if write is
+ possible while it is a shared mapping */
+ if ((flags & TARGET_BSD_MAP_FLAGMASK) == MAP_SHARED &&
+- (prot & PROT_WRITE))
++ (prot & PROT_WRITE)) {
+ return -1;
++ }
+
+ /* adjust protection to be able to read */
+- if (!(prot1 & PROT_WRITE))
++ if (!(prot1 & PROT_WRITE)) {
+ mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE);
++ }
+
+ /* read the corresponding file data */
+- pread(fd, g2h(start), end - start, offset);
++ if (pread(fd, g2h(start), end - start, offset) == -1) {
++ return -1;
++ }
+
+ /* put final protection */
+ if (prot_new != (prot1 | PROT_WRITE))
+@@ -269,13 +201,14 @@ static abi_ulong mmap_next_start = 0x40000000;
+
+ unsigned long last_brk;
+
+-/* find a free memory area of size 'size'. The search starts at
+- 'start'. If 'start' == 0, then a default start address is used.
+- Return -1 if error.
+-*/
++/*
++ * Find a free memory area of size 'size'. The search starts at
++ * 'start'. If 'start' == 0, then a default start address is used.
++ * Return -1 if error.
++ */
+ /* 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;
+@@ -300,9 +233,9 @@ static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
+ if (addr == 0)
+ addr = mmap_next_start;
+ addr_start = addr;
+- for(;;) {
++ for (;;) {
+ prot = 0;
+- for(addr1 = addr; addr1 < (addr + size); addr1 += TARGET_PAGE_SIZE) {
++ for (addr1 = addr; addr1 < (addr + size); addr1 += TARGET_PAGE_SIZE) {
+ prot |= page_get_flags(addr1);
+ }
+ if (prot == 0)
+@@ -319,9 +252,10 @@ static abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
+
+ /* NOTE: all the constants are the HOST ones */
+ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+- int flags, int fd, abi_ulong offset)
++ int flags, int fd, off_t offset)
+ {
+- abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
++ abi_ulong ret, end, real_start, real_end, retaddr, host_len;
++ off_t host_offset;
+ unsigned long host_start;
+
+ mmap_lock();
+@@ -337,21 +271,38 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+ printf("MAP_FIXED ");
+ if (flags & MAP_ANON)
+ printf("MAP_ANON ");
+- switch(flags & TARGET_BSD_MAP_FLAGMASK) {
+- case MAP_PRIVATE:
+- printf("MAP_PRIVATE ");
+- break;
+- case MAP_SHARED:
+- printf("MAP_SHARED ");
+- break;
+- default:
+- printf("[MAP_FLAGMASK=0x%x] ", flags & TARGET_BSD_MAP_FLAGMASK);
+- break;
+- }
+- printf("fd=%d offset=" TARGET_FMT_lx "\n", fd, offset);
++ if (flags & MAP_PRIVATE)
++ printf("MAP_PRIVATE ");
++ if (flags & MAP_SHARED)
++ printf("MAP_SHARED ");
++ if (flags & MAP_NOCORE)
++ printf("MAP_NOCORE ");
++#ifdef MAP_STACK
++ if (flags & MAP_STACK)
++ printf("MAP_STACK ");
++#endif
++ printf("fd=%d offset=0x%llx\n", fd, offset);
+ }
+ #endif
+
++ /*
++ * Enforce the constraints.
++ */
++ if (len == 0 && fd != -1) {
++ errno = EINVAL;
++ goto fail;
++ }
++
++#ifdef MAP_STACK
++ if (flags & MAP_STACK) {
++ if ((fd != -1) || ((prot & (PROT_READ | PROT_WRITE)) !=
++ (PROT_READ | PROT_WRITE))) {
++ errno = EINVAL;
++ goto fail;
++ }
++ }
++#endif /* MAP_STACK */
++
+ if (offset & ~TARGET_PAGE_MASK) {
+ errno = EINVAL;
+ goto fail;
+@@ -378,8 +329,9 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+ qemu_real_host_page_size */
+ p = mmap(g2h(mmap_start),
+ host_len, prot, flags | MAP_FIXED, fd, host_offset);
+- if (p == MAP_FAILED)
++ if (p == MAP_FAILED) {
+ goto fail;
++ }
+ /* update start so that it points to the file position at 'offset' */
+ host_start = (unsigned long)p;
+ if (!(flags & MAP_ANON))
+@@ -396,7 +348,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+ end = start + len;
+ real_end = HOST_PAGE_ALIGN(end);
+
+- for(addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) {
++ for (addr = real_start; addr < real_end; addr += TARGET_PAGE_SIZE) {
+ flg = page_get_flags(addr);
+ if (flg & PAGE_RESERVED) {
+ errno = ENXIO;
+@@ -493,7 +445,9 @@ 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_ABI_FMT_lx " len=0x"
++ TARGET_ABI_FMT_lx "\n",
++ start, len);
+ #endif
+ if (start & ~TARGET_PAGE_MASK)
+ return -EINVAL;
+@@ -508,11 +462,11 @@ int target_munmap(abi_ulong start, abi_ulong len)
+ if (start > real_start) {
+ /* handle host page containing start */
+ prot = 0;
+- for(addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
++ for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
+ prot |= page_get_flags(addr);
+ }
+ if (real_end == real_start + qemu_host_page_size) {
+- for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
++ for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
+ prot |= page_get_flags(addr);
+ }
+ end = real_end;
+@@ -522,7 +476,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
+ }
+ if (end < real_end) {
+ prot = 0;
+- for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
++ for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
+ prot |= page_get_flags(addr);
+ }
+ if (prot != 0)
+@@ -535,8 +489,10 @@ int target_munmap(abi_ulong start, abi_ulong len)
+ ret = munmap(g2h(real_start), real_end - real_start);
+ }
+
+- if (ret == 0)
++ if (ret == 0) {
+ page_set_flags(start, start + len, 0);
++ tb_invalidate_phys_range(start, start + len, 0);
++ }
+ mmap_unlock();
+ return ret;
+ }
+diff --git a/bsd-user/netbsd/host_os.h b/bsd-user/netbsd/host_os.h
+new file mode 100644
+index 0000000..5c492e3
+--- /dev/null
++++ b/bsd-user/netbsd/host_os.h
+@@ -0,0 +1,31 @@
++/*
++ * NetBSD host dependent code and definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __HOST_OS_H_
++#define __HOST_OS_H_
++
++#include "qemu.h"
++
++#define HOST_DEFAULT_BSD_TYPE target_netbsd
++
++static inline void save_proc_pathname(char *argv0)
++{
++ /* XXX */
++}
++
++#endif /*!__HOST_OS_H_ */
+diff --git a/bsd-user/netbsd/os-extattr.h b/bsd-user/netbsd/os-extattr.h
+new file mode 100644
+index 0000000..c2f42ac
+--- /dev/null
++++ b/bsd-user/netbsd/os-extattr.h
+@@ -0,0 +1,247 @@
++/*
++ * NetBSD extended attributes and ACL system call support
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++/* XXX To support FreeBSD targets the following will need to be added. */
++
++/* extattrctl() */
++static inline abi_long do_freebsd_extattrctl(abi_ulong arg1, abi_ulong arg2,
++ abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattrctl()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_set_file(2) */
++static inline abi_long do_freebsd_extattr_set_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_set_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_get_file(2) */
++static inline abi_long do_freebsd_extattr_get_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_get_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_delete_file(2) */
++static inline abi_long do_freebsd_extattr_delete_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_delete_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_set_fd(2) */
++static inline abi_long do_freebsd_extattr_set_fd(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_set_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_get_fd(2) */
++static inline abi_long do_freebsd_extattr_get_fd(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_get_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_delete_fd(2) */
++static inline abi_long do_freebsd_extattr_delete_fd(abi_long arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_delete_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_get_link(2) */
++static inline abi_long do_freebsd_extattr_get_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_get_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_set_link(2) */
++static inline abi_long do_freebsd_extattr_set_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_set_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_delete_link(2) */
++static inline abi_long do_freebsd_extattr_delete_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_delete_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_list_fd(2) */
++static inline abi_long do_freebsd_extattr_list_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3, abi_ulong arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall exattr_list_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_list_file(2) */
++static inline abi_long do_freebsd_extattr_list_file(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_list_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_list_link(2) */
++static inline abi_long do_freebsd_extattr_list_link(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_list_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * Access Control Lists
++ */
++
++/* __acl_aclcheck_fd(int filedes, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_aclcheck_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_aclcheck_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __acl_aclcheck_file(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_aclcheck_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_aclcheck_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __acl_aclcheck_link(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_aclcheck_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_aclcheck_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_delete_fd(int filedes, acl_type_t type); */
++static inline abi_long do_freebsd__acl_delete_fd(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_delete_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_delete_file(const char *path, acl_type_t type); */
++static inline abi_long do_freebsd__acl_delete_file(abi_ulong arg1,
++ abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_delete_fil()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_delete_link(const char *path, acl_type_t type); */
++static inline abi_long do_freebsd__acl_delete_link(abi_ulong arg1,
++ abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_delete_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_get_fd(int filedes, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_get_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_get_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __acl_get_file(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_get_file(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_get_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_get_link(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_get_link(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall _acl_get_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_get_fd(int filedes, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_set_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_set_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_set_file(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_set_file(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_set_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_set_link(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_set_link(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_set_link()\n");
++ return -TARGET_ENOSYS;
++}
++
+diff --git a/bsd-user/netbsd/os-ioctl-cmds.h b/bsd-user/netbsd/os-ioctl-cmds.h
+new file mode 100644
+index 0000000..12af33c
+--- /dev/null
++++ b/bsd-user/netbsd/os-ioctl-cmds.h
+@@ -0,0 +1,48 @@
++/* XXX should be fixed for NetBSD ioctl cmds */
++
++/* 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/netbsd/os-ioctl-filio.h b/bsd-user/netbsd/os-ioctl-filio.h
+new file mode 100644
+index 0000000..24b63ae
+--- /dev/null
++++ b/bsd-user/netbsd/os-ioctl-filio.h
+@@ -0,0 +1,29 @@
++#ifndef _IOCTL_FILIO_H_
++#define _IOCTL_FILIO_H_
++
++/* XXX needs to be fixed for NetBSD dependencies */
++
++/* 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 /* !_IOCTL_FILIO_H_ */
+diff --git a/bsd-user/netbsd/os-ioctl-ioccom.h b/bsd-user/netbsd/os-ioctl-ioccom.h
+new file mode 100644
+index 0000000..e193a16
+--- /dev/null
++++ b/bsd-user/netbsd/os-ioctl-ioccom.h
+@@ -0,0 +1,38 @@
++#ifndef _IOCTL_IOCCOM_H_
++#define _IOCTL_IOCCOM_H_
++
++/* XXX needs to be fixed for NetBSD dependencies */
++
++/*
++ * 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 /* !_IOCTL_IOCCOM_H_ */
+diff --git a/bsd-user/netbsd/os-ioctl-ttycom.h b/bsd-user/netbsd/os-ioctl-ttycom.h
+new file mode 100644
+index 0000000..9086635
+--- /dev/null
++++ b/bsd-user/netbsd/os-ioctl-ttycom.h
+@@ -0,0 +1,240 @@
++#ifndef _IOCTL_TTYCOM_H_
++#define _IOCTL_TTYCOM_H_
++
++/* XXX Needs to be fixed for NetBSD dependencies */
++
++#include "os-ioctl-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 /*! _IOCTL_TTYCOM_H_ */
+diff --git a/bsd-user/netbsd/os-ioctl-types.h b/bsd-user/netbsd/os-ioctl-types.h
+new file mode 100644
+index 0000000..e761c20
+--- /dev/null
++++ b/bsd-user/netbsd/os-ioctl-types.h
+@@ -0,0 +1,7 @@
++/* XXX should be fixed for NetBSD types and structs */
++STRUCT_SPECIAL(termios)
++
++STRUCT(winsize, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
++
++STRUCT(fiodgname_arg, TYPE_INT, TYPE_PTRVOID)
++
+diff --git a/bsd-user/netbsd/os-misc.h b/bsd-user/netbsd/os-misc.h
+new file mode 100644
+index 0000000..8be3662
+--- /dev/null
++++ b/bsd-user/netbsd/os-misc.h
+@@ -0,0 +1,375 @@
++/*
++ * miscellaneous NetBSD system call shims
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef __OS_MISC_H_
++#define __OS_MISC_H_
++
++/*
++ * XXX To support FreeBSD binaries on NetBSD these syscalls will need
++ * to be emulated.
++ */
++
++/* sched_setparam(2) */
++static inline abi_long do_freebsd_sched_setparam(pid_t pid,
++ abi_ulong target_sp_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall sched_setparam()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sched_get_param(2) */
++static inline abi_long do_freebsd_sched_getparam(pid_t pid,
++ abi_ulong target_sp_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall sched_getparam()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sched_setscheduler(2) */
++static inline abi_long do_freebsd_sched_setscheduler(pid_t pid, int policy,
++ abi_ulong target_sp_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall sched_setscheduler()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sched_getscheduler(2) */
++static inline abi_long do_freebsd_sched_getscheduler(pid_t pid)
++{
++
++ qemu_log("qemu: Unsupported syscall sched_getscheduler()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sched_getscheduler(2) */
++static inline abi_long do_freebsd_sched_rr_get_interval(pid_t pid,
++ abi_ulong target_ts_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall sched_rr_get_interval()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset(2) */
++static inline abi_long do_freebsd_cpuset(abi_ulong target_cpuid)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset_setid(2) */
++static inline abi_long do_freebsd_cpuset_setid(void *cpu_env, abi_long arg1,
++ abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset_setid()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset_getid(2) */
++static inline abi_long do_freebsd_cpuset_getid(abi_long arg1, abi_ulong arg2,
++ abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset_getid()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset_getaffinity(2) */
++static inline abi_long do_freebsd_cpuset_getaffinity(abi_long arg1,
++ abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5,
++ abi_ulong arg6)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset_getaffinity()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset_setaffinity(2) */
++static inline abi_long do_freebsd_cpuset_setaffinity(abi_long arg1,
++ abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5,
++ abi_ulong arg6)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset_setaffinity()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* modfnext(2) */
++static inline abi_long do_freebsd_modfnext(abi_long modid)
++{
++
++ qemu_log("qemu: Unsupported syscall modfnext()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* modfind(2) */
++static inline abi_long do_freebsd_modfind(abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall modfind()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldload(2) */
++static inline abi_long do_freebsd_kldload(abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall kldload()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldunload(2) */
++static inline abi_long do_freebsd_kldunload(abi_long fileid)
++{
++
++ qemu_log("qemu: Unsupported syscall kldunload()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldunloadf(2) */
++static inline abi_long do_freebsd_kldunloadf(abi_long fileid, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall kldunloadf()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldfind(2) */
++static inline abi_long do_freebsd_kldfind(abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall kldfind()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldnext(2) */
++static inline abi_long do_freebsd_kldnext(abi_long fileid)
++{
++
++ qemu_log("qemu: Unsupported syscall kldnext()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* kldstat(2) */
++static inline abi_long do_freebsd_kldstat(abi_long fileid,
++ abi_ulong target_stat)
++{
++
++ qemu_log("qemu: Unsupported syscall kldstat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldfirstmod(2) */
++static inline abi_long do_freebsd_kldfirstmod(abi_long fileid)
++{
++
++ qemu_log("qemu: Unsupported syscall kldfirstmod()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldsym(2) */
++static inline abi_long do_freebsd_kldsym(abi_long fileid, abi_long cmd,
++ abi_ulong target_data)
++{
++
++ qemu_log("qemu: Unsupported syscall kldsym()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * Resource limits (undocumented except for rctl(8) and rctl.conf(5) )
++ */
++/* rctl_get_racct() */
++static inline abi_long do_freebsd_rctl_get_racct(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_get_racct()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_get_rules() */
++static inline abi_long do_freebsd_rctl_get_rules(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_get_rules()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_add_rule() */
++static inline abi_long do_freebsd_rctl_add_rule(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_add_rule()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_remove_rule() */
++static inline abi_long do_freebsd_rctl_remove_rule(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_remove_rule()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_get_limits() */
++static inline abi_long do_freebsd_rctl_get_limits(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_get_limits()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * Kernel environment
++ */
++
++/* kenv(2) */
++static inline abi_long do_freebsd_kenv(abi_long what, abi_ulong target_name,
++ abi_ulong target_value, abi_long len)
++{
++
++ qemu_log("qemu: Unsupported syscall kenv()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/*
++ * Mandatory Access Control
++ */
++
++/* __mac_get_proc */
++static inline abi_long do_freebsd___mac_get_proc(abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_proc()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_proc */
++static inline abi_long do_freebsd___mac_set_proc(abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_proc()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* __mac_get_fd */
++static inline abi_long do_freebsd___mac_get_fd(abi_long fd,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_fd */
++static inline abi_long do_freebsd___mac_set_fd(abi_long fd,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_get_file */
++static inline abi_long do_freebsd___mac_get_file(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_file */
++static inline abi_long do_freebsd___mac_set_file(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_get_link */
++static inline abi_long do_freebsd___mac_get_link(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_link */
++static inline abi_long do_freebsd___mac_set_link(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* mac_syscall */
++static inline abi_long do_freebsd_mac_syscall(abi_ulong target_policy,
++ abi_long call, abi_ulong target_arg)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_syscall()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/*
++ * New posix calls
++ */
++/* posix_fallocate(2) */
++static inline abi_long do_freebsd_posix_fallocate(abi_long fd, abi_ulong offset,
++ abi_ulong len)
++{
++
++ qemu_log("qemu: Unsupported syscall posix_fallocate()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* posix_openpt(2) */
++static inline abi_long do_freebsd_posix_openpt(abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall posix_openpt()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* posix_fadvise(2) */
++static inline abi_long do_freebsd_posix_fadvise(abi_long fd, abi_ulong offset,
++ abi_ulong len, abi_long advise)
++{
++
++ qemu_log("qemu: Unsupported syscall posix_fadvise()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* ! __OS_MISC_H_ */
+diff --git a/bsd-user/netbsd/os-proc.c b/bsd-user/netbsd/os-proc.c
+new file mode 100644
+index 0000000..bc11d29
+--- /dev/null
++++ b/bsd-user/netbsd/os-proc.c
+@@ -0,0 +1,11 @@
++/*
++ * XXX To support FreeBSD binaries on NetBSD the following will need to be
++ * emulated.
++ */
++abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
++ abi_ulong guest_envp, int do_fexec)
++{
++
++ qemu_log("qemu: Unsupported %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
+diff --git a/bsd-user/netbsd/os-proc.h b/bsd-user/netbsd/os-proc.h
+new file mode 100644
+index 0000000..f34d616
+--- /dev/null
++++ b/bsd-user/netbsd/os-proc.h
+@@ -0,0 +1,243 @@
++#ifndef __NETBSD_PROC_H_
++#define __NETBSD_PROC_H_
++
++/*
++ * XXX To support FreeBSD binaries on NetBSD these syscalls will need
++ * to be emulated.
++ */
++
++/* execve(2) */
++static inline abi_long do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp,
++ abi_ulong envp)
++{
++
++ qemu_log("qemu: Unsupported syscall execve()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fexecve(2) */
++static inline abi_long do_freebsd_fexecve(abi_ulong path_or_fd, abi_ulong argp,
++ abi_ulong envp)
++{
++
++ qemu_log("qemu: Unsupported syscall fexecve()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* wait4(2) */
++static inline abi_long do_freebsd_wait4(abi_long arg1, abi_ulong target_status,
++ abi_long arg3, abi_ulong target_rusage)
++{
++
++ qemu_log("qemu: Unsupported syscall wait4()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setloginclass(2) */
++static inline abi_long do_freebsd_setloginclass(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall setloginclass()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getloginclass(2) */
++static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall getloginclass()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* pdwait4(2) */
++static inline abi_long do_freebsd_pdwait4(abi_long arg1,
++ abi_ulong target_status, abi_long arg3, abi_ulong target_rusage)
++{
++
++ qemu_log("qemu: Unsupported syscall pdwait4()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* pdgetpid(2) */
++static inline abi_long do_freebsd_pdgetpid(abi_long fd, abi_ulong target_pidp)
++{
++
++ qemu_log("qemu: Unsupported syscall pdgetpid()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* undocumented __setugid */
++static inline abi_long do_freebsd___setugid(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall __setugid()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fork(2) */
++static inline abi_long do_freebsd_fork(void *cpu_env)
++{
++
++ qemu_log("qemu: Unsupported syscall fork()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* vfork(2) */
++static inline abi_long do_freebsd_vfork(void *cpu_env)
++{
++
++ qemu_log("qemu: Unsupported syscall vfork()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rfork(2) */
++static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall rfork()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* pdfork(2) */
++static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong arg1,
++ abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall pdfork()\n");
++ return -TARGET_ENOSYS
++}
++
++/* jail(2) */
++static inline abi_long do_freebsd_jail(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall jail()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_attach(2) */
++static inline abi_long do_freebsd_jail_attach(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_attach()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_remove(2) */
++static inline abi_long do_freebsd_jail_remove(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_remove()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_get(2) */
++static inline abi_long do_freebsd_jail_get(abi_ulong arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_get()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_set(2) */
++static inline abi_long do_freebsd_jail_set(abi_ulong arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_set()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_enter(2) */
++static inline abi_long do_freebsd_cap_enter(void)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_enter()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_new(2) */
++static inline abi_long do_freebsd_cap_new(abi_long arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_new()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_getrights(2) */
++static inline abi_long do_freebsd_cap_getrights(abi_long arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_getrights()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_getmode(2) */
++static inline abi_long do_freebsd_cap_getmode(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_getmode()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* audit(2) */
++static inline abi_long do_freebsd_audit(abi_ulong arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall audit()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* auditon(2) */
++static inline abi_long do_freebsd_auditon(abi_long arg1, abi_ulong arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall auditon()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getaudit(2) */
++static inline abi_long do_freebsd_getaudit(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall getaudit()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setaudit(2) */
++static inline abi_long do_freebsd_setaudit(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall setaudit()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getaudit_addr(2) */
++static inline abi_long do_freebsd_getaudit_addr(abi_ulong arg1,
++ abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall getaudit_addr()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setaudit_addr(2) */
++static inline abi_long do_freebsd_setaudit_addr(abi_ulong arg1,
++ abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall setaudit_addr()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* auditctl(2) */
++static inline abi_long do_freebsd_auditctl(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall auditctl()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* ! __NETBSD_PROC_H_ */
+diff --git a/bsd-user/netbsd/os-socket.c b/bsd-user/netbsd/os-socket.c
+new file mode 100644
+index 0000000..d983c34
+--- /dev/null
++++ b/bsd-user/netbsd/os-socket.c
+@@ -0,0 +1 @@
++/* XXX NetBSD socket related helpers */
+diff --git a/bsd-user/netbsd/os-socket.h b/bsd-user/netbsd/os-socket.h
+new file mode 100644
+index 0000000..a49c41d
+--- /dev/null
++++ b/bsd-user/netbsd/os-socket.h
+@@ -0,0 +1,98 @@
++/*
++ * NetBSD socket related system call shims
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef __NETBSD_SOCKET_H_
++#define __NETBSD_SOCKET_H_
++
++/*
++ * XXX To support FreeBSD binaries on NetBSD these syscalls will need
++ * to be emulated.
++ */
++
++/* sendmsg(2) */
++static inline abi_long do_freebsd_sendmsg(int fd, abi_ulong target_msg,
++ int flags)
++{
++
++ qemu_log("qemu: Unsupported syscall sendmsg()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* recvmsg(2) */
++static inline abi_long do_freebsd_recvmsg(int fd, abi_ulong target_msg,
++ int flags)
++{
++
++ qemu_log("qemu: Unsupported syscall recvmsg()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setsockopt(2) */
++static inline abi_long do_bsd_setsockopt(int sockfd, int level, int optname,
++ abi_ulong optval_addr, socklen_t optlen)
++{
++
++ qemu_log("qemu: Unsupported syscall setsockopt()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getsockopt(2) */
++static inline abi_long do_bsd_getsockopt(int sockfd, int level, int optname,
++ abi_ulong optval_addr, abi_ulong optlen)
++{
++
++ qemu_log("qemu: Unsupported syscall getsockopt()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setfib(2) */
++static inline abi_long do_freebsd_setfib(abi_long fib)
++{
++
++ qemu_log("qemu: Unsupported syscall setfib()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sctp_peeloff(2) */
++static inline abi_long do_freebsd_sctp_peeloff(abi_long s, abi_ulong id)
++{
++
++ qemu_log("qemu: Unsupported syscall sctp_peeloff()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sctp_generic_sendmsg(2) */
++static inline abi_long do_freebsd_sctp_generic_sendmsg(abi_long s,
++ abi_ulong target_msg, abi_long msglen, abi_ulong target_to,
++ abi_ulong len, abi_ulong target_sinfo, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall sctp_generic_sendmsg()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sctp_generic_recvmsg(2) */
++static inline abi_long do_freebsd_sctp_generic_recvmsg(abi_long s,
++ abi_ulong target_iov, abi_long iovlen, abi_ulong target_from,
++ abi_ulong fromlen, abi_ulong target_sinfo, abi_ulong target_msgflags)
++{
++
++ qemu_log("qemu: Unsupported syscall sctp_generic_recvmsg()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* !__NETBSD_SOCKET_H_ */
+diff --git a/bsd-user/netbsd/os-stat.c b/bsd-user/netbsd/os-stat.c
+new file mode 100644
+index 0000000..11ea122
+--- /dev/null
++++ b/bsd-user/netbsd/os-stat.c
+@@ -0,0 +1 @@
++/* XXX NetBSD stat related helpers */
+diff --git a/bsd-user/netbsd/os-stat.h b/bsd-user/netbsd/os-stat.h
+new file mode 100644
+index 0000000..11ea122
+--- /dev/null
++++ b/bsd-user/netbsd/os-stat.h
+@@ -0,0 +1 @@
++/* XXX NetBSD stat related helpers */
+diff --git a/bsd-user/netbsd/os-strace.h b/bsd-user/netbsd/os-strace.h
+new file mode 100644
+index 0000000..70cf51d
+--- /dev/null
++++ b/bsd-user/netbsd/os-strace.h
+@@ -0,0 +1 @@
++/* XXX NetBSD dependent strace print functions */
+diff --git a/bsd-user/netbsd/os-sys.c b/bsd-user/netbsd/os-sys.c
+new file mode 100644
+index 0000000..68ea0e1
+--- /dev/null
++++ b/bsd-user/netbsd/os-sys.c
+@@ -0,0 +1,46 @@
++/*
++ * NetBSD sysctl() and sysarch() system call emulation
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <sys/param.h>
++#include <sys/sysctl.h>
++#include <string.h>
++
++#include "qemu.h"
++
++#include "target_arch_sysarch.h"
++#include "target_os_vmparam.h"
++
++
++/* This must be emulated to support FreeBSD target binaries on NetBSD host. */
++
++abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen,
++ abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen)
++{
++
++ qemu_log("qemu: Unsupported syscall __sysctl()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sysarch() is architecture dependent. */
++abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall sysarch()\n");
++ return -TARGET_ENOSYS;
++}
+diff --git a/bsd-user/netbsd/os-thread.c b/bsd-user/netbsd/os-thread.c
+new file mode 100644
+index 0000000..a4af765
+--- /dev/null
++++ b/bsd-user/netbsd/os-thread.c
+@@ -0,0 +1 @@
++/* XXX NetBSD thread related helpers */
+diff --git a/bsd-user/netbsd/os-thread.h b/bsd-user/netbsd/os-thread.h
+new file mode 100644
+index 0000000..073b0a0
+--- /dev/null
++++ b/bsd-user/netbsd/os-thread.h
+@@ -0,0 +1,133 @@
++#ifndef __NETBSD_OS_THREAD_H_
++#define __NETBSD_OS_THREAD_H_
++
++/*
++ * XXX To support FreeBSD binaries on NetBSD these syscalls will need to
++ * be emulated.
++ */
++static abi_long do_freebsd_thr_create(CPUArchState *env, abi_ulong target_ctx,
++ abi_ulong target_id, int flags)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_create()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_create(CPUArchState *env, abi_ulong thread_ctx,
++ abi_ulong target_id, int flags)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_create()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_new(CPUArchState *env,
++ abi_ulong target_param_addr, int32_t param_size)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_new()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_self(abi_ulong target_id)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_self()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_exit(CPUArchState *cpu_env, abi_ulong tid_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_exit()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_kill(long id, int sig)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_kill()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_kill2(pid_t pid, long id, int sig)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_kill2()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_suspend(abi_ulong target_ts)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_suspend()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_wake(long tid)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_wake()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_set_name(long tid, abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_set_name()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_rtprio_thread(int function, lwpid_t lwpid,
++ abi_ulong target_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall rtprio_thread()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_getcontext(void *cpu_env, abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall getcontext()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_setcontext(void *cpu_env, abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall setcontext()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_swapcontext(void *cpu_env, abi_ulong arg1,
++ abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall swapcontext()\n");
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd__umtx_lock(abi_ulong target_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall _umtx_lock()\n");
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd__umtx_unlock(abi_ulong target_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall _umtx_unlock()\n");
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd__umtx_op(abi_ulong obj, int op, abi_ulong val,
++ abi_ulong uaddr, abi_ulong target_ts)
++{
++
++ qemu_log("qemu: Unsupported syscall _umtx_op()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* ! __NETBSD_OS_THREAD_H_ */
+diff --git a/bsd-user/netbsd/os-time.c b/bsd-user/netbsd/os-time.c
+new file mode 100644
+index 0000000..ee2c7a0
+--- /dev/null
++++ b/bsd-user/netbsd/os-time.c
+@@ -0,0 +1 @@
++/* XXX NetBSD time related helpers */
+diff --git a/bsd-user/netbsd/os-time.h b/bsd-user/netbsd/os-time.h
+new file mode 100644
+index 0000000..6d0f1de
+--- /dev/null
++++ b/bsd-user/netbsd/os-time.h
+@@ -0,0 +1,179 @@
++#ifndef __NETBSD_OS_TIME_H_
++#define __NETBSD_OS_TIME_H_
++
++/*
++ * XXX To support FreeBSD binaries on NetBSD these syscalls will need to
++ * be emulated.
++ */
++static inline abi_long do_freebsd_nanosleep(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_clock_gettime(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_clock_settime(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_clock_getres(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_gettimeofday(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_settimeofday(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_adjtime(abi_ulong target_delta_addr,
++ abi_ulong target_old_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_ntp_adjtime(abi_ulong target_tx_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_ntp_gettime(abi_ulong target_ntv_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_utimes(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_lutimes(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_futimes(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_futimesat(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_ktimer_create(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_ktimer_delete(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_ktimer_settime(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_ktimer_gettime(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_ktimer_getoverrun(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_select(int n, abi_ulong rfd_addr,
++ abi_ulong wfd_addr, abi_ulong efd_addr, abi_ulong target_tv_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++
++static inline 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)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_kqueue(void)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_kevent(abi_long arg1, abi_ulong arg2,
++ abi_long arg3, abi_ulong arg4, abi_long arg5, abi_long arg6)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_sigtimedwait(abi_ulong arg1, abi_ulong arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++#endif /* ! __NETBSD_OS_TIME_H_ */
+diff --git a/bsd-user/netbsd/qemu-os.h b/bsd-user/netbsd/qemu-os.h
+new file mode 100644
+index 0000000..016618b
+--- /dev/null
++++ b/bsd-user/netbsd/qemu-os.h
+@@ -0,0 +1 @@
++/* NetBSD conversion extern declarations */
+diff --git a/bsd-user/netbsd/target_os_elf.h b/bsd-user/netbsd/target_os_elf.h
+new file mode 100644
+index 0000000..bf663d2
+--- /dev/null
++++ b/bsd-user/netbsd/target_os_elf.h
+@@ -0,0 +1,226 @@
++/*
++ * netbsd ELF definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_OS_ELF_H_
++#define _TARGET_OS_ELF_H_
++
++#include "target_arch_elf.h"
++#include "elf.h"
++
++/* from personality.h */
++
++/*
++ * Flags for bug emulation.
++ *
++ * These occupy the top three bytes.
++ */
++enum {
++ ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA
++ space */
++ FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs
++ point to descriptors
++ (signal handling) */
++ MMAP_PAGE_ZERO = 0x0100000,
++ ADDR_COMPAT_LAYOUT = 0x0200000,
++ READ_IMPLIES_EXEC = 0x0400000,
++ ADDR_LIMIT_32BIT = 0x0800000,
++ SHORT_INODE = 0x1000000,
++ WHOLE_SECONDS = 0x2000000,
++ STICKY_TIMEOUTS = 0x4000000,
++ ADDR_LIMIT_3GB = 0x8000000,
++};
++
++/*
++ * Personality types.
++ *
++ * These go in the low byte. Avoid using the top bit, it will
++ * conflict with error returns.
++ */
++enum {
++ PER_LINUX = 0x0000,
++ PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
++ PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
++ PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
++ PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
++ PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS |
++ WHOLE_SECONDS | SHORT_INODE,
++ PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
++ PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
++ PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
++ PER_BSD = 0x0006,
++ PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
++ PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
++ PER_LINUX32 = 0x0008,
++ PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
++ PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
++ PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
++ PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
++ PER_RISCOS = 0x000c,
++ PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
++ PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
++ PER_OSF4 = 0x000f, /* OSF/1 v4 */
++ PER_HPUX = 0x0010,
++ PER_MASK = 0x00ff,
++};
++
++/*
++ * Return the base personality without flags.
++ */
++#define personality(pers) (pers & PER_MASK)
++
++/* this flag is uneffective under linux too, should be deleted */
++#ifndef MAP_DENYWRITE
++#define MAP_DENYWRITE 0
++#endif
++
++/* should probably go in elf.h */
++#ifndef ELIBBAD
++#define ELIBBAD 80
++#endif
++
++#ifndef ELF_PLATFORM
++#define ELF_PLATFORM (NULL)
++#endif
++
++#ifndef ELF_HWCAP
++#define ELF_HWCAP 0
++#endif
++
++#ifdef TARGET_ABI32
++#undef ELF_CLASS
++#define ELF_CLASS ELFCLASS32
++#undef bswaptls
++#define bswaptls(ptr) bswap32s(ptr)
++#endif
++
++struct exec
++{
++ unsigned int a_info; /* Use macros N_MAGIC, etc for access */
++ unsigned int a_text; /* length of text, in bytes */
++ unsigned int a_data; /* length of data, in bytes */
++ unsigned int a_bss; /* length of uninitialized data area, in bytes */
++ unsigned int a_syms; /* length of symbol table data in file, in bytes */
++ unsigned int a_entry; /* start address */
++ unsigned int a_trsize; /* length of relocation info for text, in bytes */
++ unsigned int a_drsize; /* length of relocation info for data, in bytes */
++};
++
++
++#define N_MAGIC(exec) ((exec).a_info & 0xffff)
++#define OMAGIC 0407
++#define NMAGIC 0410
++#define ZMAGIC 0413
++#define QMAGIC 0314
++
++/* max code+data+bss space allocated to elf interpreter */
++#define INTERP_MAP_SIZE (32 * 1024 * 1024)
++
++/* max code+data+bss+brk space allocated to ET_DYN executables */
++#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
++
++/* Necessary parameters */
++#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
++#define TARGET_ELF_PAGESTART(_v) ((_v) & \
++ ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
++#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
++
++#define INTERPRETER_NONE 0
++#define INTERPRETER_AOUT 1
++#define INTERPRETER_ELF 2
++
++#define DLINFO_ITEMS 12
++
++static abi_ulong target_create_elf_tables(abi_ulong p, int argc, int envc,
++ struct elfhdr * exec,
++ abi_ulong load_addr,
++ abi_ulong load_bias,
++ abi_ulong interp_load_addr, int ibcs,
++ struct image_info *info)
++{
++ abi_ulong sp;
++ int size;
++ abi_ulong u_platform;
++ const char *k_platform;
++ const int n = sizeof(elf_addr_t);
++
++ sp = p;
++ u_platform = 0;
++ k_platform = ELF_PLATFORM;
++ if (k_platform) {
++ size_t len = strlen(k_platform) + 1;
++ sp -= (len + n - 1) & ~(n - 1);
++ u_platform = sp;
++ /* FIXME - check return value of memcpy_to_target() for failure */
++ memcpy_to_target(sp, k_platform, len);
++ }
++ /*
++ * Force 16 byte _final_ alignment here for generality.
++ */
++ sp = sp &~ (abi_ulong)15;
++ size = (DLINFO_ITEMS + 1) * 2;
++ if (k_platform)
++ size += 2;
++#ifdef DLINFO_ARCH_ITEMS
++ size += DLINFO_ARCH_ITEMS * 2;
++#endif
++ size += envc + argc + 2;
++ size += (!ibcs ? 3 : 1); /* argc itself */
++ size *= n;
++ if (size & 15)
++ sp -= 16 - (size & 15);
++
++ /* This is correct because Linux defines
++ * elf_addr_t as Elf32_Off / Elf64_Off
++ */
++#define NEW_AUX_ENT(id, val) do { \
++ sp -= n; put_user_ual(val, sp); \
++ sp -= n; put_user_ual(id, sp); \
++ } while(0)
++
++ NEW_AUX_ENT (AT_NULL, 0);
++
++ /* There must be exactly DLINFO_ITEMS entries here. */
++ NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
++ NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
++ NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
++ NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
++ NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
++ NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
++ NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
++ NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
++ NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
++ NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
++ 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));
++ if (k_platform)
++ NEW_AUX_ENT(AT_PLATFORM, u_platform);
++#ifdef ARCH_DLINFO
++ /*
++ * ARCH_DLINFO must come last so platform specific code can enforce
++ * special alignment requirements on the AUXV if necessary (eg. PPC).
++ */
++ ARCH_DLINFO;
++#endif
++#undef NEW_AUX_ENT
++
++ sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
++ return sp;
++}
++
++#endif /* _TARGET_OS_ELF_H_ */
+diff --git a/bsd-user/netbsd/target_os_siginfo.h b/bsd-user/netbsd/target_os_siginfo.h
+new file mode 100644
+index 0000000..667c19c
+--- /dev/null
++++ b/bsd-user/netbsd/target_os_siginfo.h
+@@ -0,0 +1,82 @@
++#ifndef _TARGET_OS_SIGINFO_H_
++#define _TARGET_OS_SIGINFO_H_
++
++#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */
++#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
++#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
++
++/* 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;
++};
++
++/* Compare to sys/siginfo.h */
++typedef union target_sigval {
++ int sival_int;
++ abi_ulong sival_ptr;
++} target_sigval_t;
++
++struct target_ksiginfo {
++ int32_t _signo;
++ int32_t _code;
++ int32_t _errno;
++#if TARGET_ABI_BITS == 64
++ int32_t _pad;
++#endif
++ union {
++ struct {
++ int32_t _pid;
++ int32_t _uid;
++ target_sigval_t _value;
++ } _rt;
++
++ struct {
++ int32_t _pid;
++ int32_t _uid;
++ int32_t _struct;
++ /* clock_t _utime; */
++ /* clock_t _stime; */
++ } _child;
++
++ struct {
++ abi_ulong _addr;
++ int32_t _trap;
++ } _fault;
++
++ struct {
++ long _band;
++ int _fd;
++ } _poll;
++ } _reason;
++};
++
++typedef union target_siginfo {
++ int8_t si_pad[128];
++ struct target_ksiginfo _info;
++} target_siginfo_t;
++
++#define target_si_signo _info._signo
++#define target_si_code _info._code
++#define target_si_errno _info._errno
++#define target_si_addr _info._reason._fault._addr
++
++#define TARGET_SEGV_MAPERR 1
++#define TARGET_SEGV_ACCERR 2
++
++#define TARGET_TRAP_BRKPT 1
++#define TARGET_TRAP_TRACE 2
++
++
++#endif /* ! _TARGET_OS_SIGINFO_H_ */
+diff --git a/bsd-user/netbsd/target_os_signal.h b/bsd-user/netbsd/target_os_signal.h
+new file mode 100644
+index 0000000..d39a26f
+--- /dev/null
++++ b/bsd-user/netbsd/target_os_signal.h
+@@ -0,0 +1,70 @@
++#ifndef _TARGET_OS_SIGNAL_H_
++#define _TARGET_OS_SIGNAL_H_
++
++#include "target_os_siginfo.h"
++#include "target_arch_signal.h"
++
++#define TARGET_SIGHUP 1 /* hangup */
++#define TARGET_SIGINT 2 /* interrupt */
++#define TARGET_SIGQUIT 3 /* quit */
++#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught) */
++#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
++#define TARGET_SIGABRT 6 /* abort() */
++#define TARGET_SIGIOT SIGABRT /* compatibility */
++#define TARGET_SIGEMT 7 /* EMT instruction */
++#define TARGET_SIGFPE 8 /* floating point exception */
++#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
++#define TARGET_SIGBUS 10 /* bus error */
++#define TARGET_SIGSEGV 11 /* segmentation violation */
++#define TARGET_SIGSYS 12 /* bad argument to system call */
++#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
++#define TARGET_SIGALRM 14 /* alarm clock */
++#define TARGET_SIGTERM 15 /* software termination signal from kill */
++#define TARGET_SIGURG 16 /* urgent condition on IO channel */
++#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
++#define TARGET_SIGTSTP 18 /* stop signal from tty */
++#define TARGET_SIGCONT 19 /* continue a stopped process */
++#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
++#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
++#define TARGET_SIGTTOU 22 /* like TTIN for output if
++ (tp->t_local&LTOSTOP) */
++#define TARGET_SIGIO 23 /* input/output possible signal */
++#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
++#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
++#define TARGET_SIGVTALRM 26 /* virtual time alarm */
++#define TARGET_SIGPROF 27 /* profiling time alarm */
++#define TARGET_SIGWINCH 28 /* window size changes */
++#define TARGET_SIGINFO 29 /* information request */
++#define TARGET_SIGUSR1 30 /* user defined signal 1 */
++#define TARGET_SIGUSR2 31 /* user defined signal 2 */
++
++/*
++ * 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_SA_ONSTACK 0x0001 /* take signal on signal stack */
++#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
++#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
++#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering */
++#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1) */
++#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
++#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
++#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
++
++/*
++ * Flags for sigprocmask:
++ */
++#define TARGET_SIG_BLOCK 1 /* block specified signal set */
++#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
++#define TARGET_SIG_SETMASK 3 /* set specified signal set */
++
++#define TARGET_BADSIG SIG_ERR
++
++#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
++#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack */
++
++#endif /* !_TARGET_OS_SIGNAL_H_ */
+diff --git a/bsd-user/netbsd/target_os_stack.h b/bsd-user/netbsd/target_os_stack.h
+new file mode 100644
+index 0000000..1a26c3f
+--- /dev/null
++++ b/bsd-user/netbsd/target_os_stack.h
+@@ -0,0 +1,33 @@
++#ifndef _TARGET_OS_STACK_H_
++#define _TARGET_OS_STACK_H_
++
++#include "target_arch_sigtramp.h"
++
++static inline int setup_initial_stack(struct bsd_binprm *bprm, abi_ulong *p)
++{
++ int i;
++ abi_ulong stack_base;
++
++ stack_base = (target_stkbas + target_stksiz) -
++ MAX_ARG_PAGES * TARGET_PAGE_SIZE;
++ if (p) {
++ *p = stack_base;
++ }
++
++ for (i = 0; i < MAX_ARG_PAGES; i++) {
++ if (bprm->page[i]) {
++ info->rss++;
++ if (!memcpy_to_target(stack_base, bprm->page[i],
++ TARGET_PAGE_SIZE)) {
++ errno = EFAULT;
++ return -1;
++ }
++ g_free(bprm->page[i]);
++ }
++ stack_base += TARGET_PAGE_SIZE;
++ }
++
++ return 0;
++}
++
++#endif /* !_TARGET_OS_STACK_H_ */
+diff --git a/bsd-user/netbsd/target_os_thread.h b/bsd-user/netbsd/target_os_thread.h
+new file mode 100644
+index 0000000..519aad8
+--- /dev/null
++++ b/bsd-user/netbsd/target_os_thread.h
+@@ -0,0 +1,6 @@
++#ifndef _TARGET_OS_THREAD_H_
++#define _TARGET_OS_THREAD_H_
++
++#include "target_arch_thread.h"
++
++#endif /* !_TARGET_OS_THREAD_H_ */
+diff --git a/bsd-user/openbsd/host_os.h b/bsd-user/openbsd/host_os.h
+new file mode 100644
+index 0000000..162ce58
+--- /dev/null
++++ b/bsd-user/openbsd/host_os.h
+@@ -0,0 +1,31 @@
++/*
++ * OpenBSD host dependent code and definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __HOST_OS_H_
++#define __HOST_OS_H_
++
++#include "qemu.h"
++
++#define HOST_DEFAULT_BSD_TYPE target_openbsd
++
++static inline void save_proc_pathname(char *argv0)
++{
++ /* XXX */
++}
++
++#endif /*!__HOST_OS_H_ */
+diff --git a/bsd-user/openbsd/os-extattr.h b/bsd-user/openbsd/os-extattr.h
+new file mode 100644
+index 0000000..5c23af3
+--- /dev/null
++++ b/bsd-user/openbsd/os-extattr.h
+@@ -0,0 +1,247 @@
++/*
++ * OpenBSD extended attributes and ACL system call support
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++/* XXX To support FreeBSD targets the following will need to be added. */
++
++/* extattrctl() */
++static inline abi_long do_freebsd_extattrctl(abi_ulong arg1, abi_ulong arg2,
++ abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattrctl()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_set_file(2) */
++static inline abi_long do_freebsd_extattr_set_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_set_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_get_file(2) */
++static inline abi_long do_freebsd_extattr_get_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_get_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_delete_file(2) */
++static inline abi_long do_freebsd_extattr_delete_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_delete_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_set_fd(2) */
++static inline abi_long do_freebsd_extattr_set_fd(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_set_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_get_fd(2) */
++static inline abi_long do_freebsd_extattr_get_fd(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_get_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_delete_fd(2) */
++static inline abi_long do_freebsd_extattr_delete_fd(abi_long arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_delete_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_get_link(2) */
++static inline abi_long do_freebsd_extattr_get_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_get_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_set_link(2) */
++static inline abi_long do_freebsd_extattr_set_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_set_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_delete_link(2) */
++static inline abi_long do_freebsd_extattr_delete_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_delete_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_list_fd(2) */
++static inline abi_long do_freebsd_extattr_list_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3, abi_ulong arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall exattr_list_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_list_file(2) */
++static inline abi_long do_freebsd_extattr_list_file(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_list_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* extattr_list_link(2) */
++static inline abi_long do_freebsd_extattr_list_link(abi_long arg1,
++ abi_long arg2, abi_ulong arg3, abi_ulong arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall extattr_list_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * Access Control Lists
++ */
++
++/* __acl_aclcheck_fd(int filedes, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_aclcheck_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_aclcheck_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __acl_aclcheck_file(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_aclcheck_file(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_aclcheck_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __acl_aclcheck_link(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_aclcheck_link(abi_ulong arg1,
++ abi_long arg2, abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_aclcheck_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_delete_fd(int filedes, acl_type_t type); */
++static inline abi_long do_freebsd__acl_delete_fd(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_delete_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_delete_file(const char *path, acl_type_t type); */
++static inline abi_long do_freebsd__acl_delete_file(abi_ulong arg1,
++ abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_delete_fil()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_delete_link(const char *path, acl_type_t type); */
++static inline abi_long do_freebsd__acl_delete_link(abi_ulong arg1,
++ abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_delete_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_get_fd(int filedes, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_get_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_get_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __acl_get_file(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_get_file(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_get_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_get_link(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_get_link(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall _acl_get_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_get_fd(int filedes, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_set_fd(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_set_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_set_file(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_set_file(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_set_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* int __acl_set_link(const char *path, acl_type_t type, struct acl *aclp); */
++static inline abi_long do_freebsd__acl_set_link(abi_ulong arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall __acl_set_link()\n");
++ return -TARGET_ENOSYS;
++}
++
+diff --git a/bsd-user/openbsd/os-ioctl-cmds.h b/bsd-user/openbsd/os-ioctl-cmds.h
+new file mode 100644
+index 0000000..a15f056
+--- /dev/null
++++ b/bsd-user/openbsd/os-ioctl-cmds.h
+@@ -0,0 +1,48 @@
++/* XXX should be fixed for OpenBSD ioctl cmds */
++
++/* 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/openbsd/os-ioctl-filio.h b/bsd-user/openbsd/os-ioctl-filio.h
+new file mode 100644
+index 0000000..e3f7474
+--- /dev/null
++++ b/bsd-user/openbsd/os-ioctl-filio.h
+@@ -0,0 +1,29 @@
++#ifndef _IOCTL_FILIO_H_
++#define _IOCTL_FILIO_H_
++
++/* XXX needs to be fixed for OpenBSD dependencies */
++
++/* 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 /* !_IOCTL_FILIO_H_ */
+diff --git a/bsd-user/openbsd/os-ioctl-ioccom.h b/bsd-user/openbsd/os-ioctl-ioccom.h
+new file mode 100644
+index 0000000..fa1c6b4
+--- /dev/null
++++ b/bsd-user/openbsd/os-ioctl-ioccom.h
+@@ -0,0 +1,38 @@
++#ifndef _IOCTL_IOCCOM_H_
++#define _IOCTL_IOCCOM_H_
++
++/* XXX needs to be fixed for OpenBSD dependencies */
++
++/*
++ * 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 /* !_IOCTL_IOCCOM_H_ */
+diff --git a/bsd-user/openbsd/os-ioctl-ttycom.h b/bsd-user/openbsd/os-ioctl-ttycom.h
+new file mode 100644
+index 0000000..745d702
+--- /dev/null
++++ b/bsd-user/openbsd/os-ioctl-ttycom.h
+@@ -0,0 +1,240 @@
++#ifndef _IOCTL_TTYCOM_H_
++#define _IOCTL_TTYCOM_H_
++
++/* XXX Needs to be fixed for OpenBSD dependencies */
++
++#include "os-ioctl-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 /*! _IOCTL_TTYCOM_H_ */
+diff --git a/bsd-user/openbsd/os-ioctl-types.h b/bsd-user/openbsd/os-ioctl-types.h
+new file mode 100644
+index 0000000..6f8b97b
+--- /dev/null
++++ b/bsd-user/openbsd/os-ioctl-types.h
+@@ -0,0 +1,7 @@
++/* XXX should be fixed for OpenBSD types and structs */
++STRUCT_SPECIAL(termios)
++
++STRUCT(winsize, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
++
++STRUCT(fiodgname_arg, TYPE_INT, TYPE_PTRVOID)
++
+diff --git a/bsd-user/openbsd/os-misc.h b/bsd-user/openbsd/os-misc.h
+new file mode 100644
+index 0000000..5a17ac9
+--- /dev/null
++++ b/bsd-user/openbsd/os-misc.h
+@@ -0,0 +1,375 @@
++/*
++ * miscellaneous OpenBSD system call shims
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef __OS_MISC_H_
++#define __OS_MISC_H_
++
++/*
++ * XXX To support FreeBSD binaries on OpenBSD these syscalls will need
++ * to be emulated.
++ */
++
++/* sched_setparam(2) */
++static inline abi_long do_freebsd_sched_setparam(pid_t pid,
++ abi_ulong target_sp_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall sched_setparam()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sched_get_param(2) */
++static inline abi_long do_freebsd_sched_getparam(pid_t pid,
++ abi_ulong target_sp_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall sched_getparam()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sched_setscheduler(2) */
++static inline abi_long do_freebsd_sched_setscheduler(pid_t pid, int policy,
++ abi_ulong target_sp_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall sched_setscheduler()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sched_getscheduler(2) */
++static inline abi_long do_freebsd_sched_getscheduler(pid_t pid)
++{
++
++ qemu_log("qemu: Unsupported syscall sched_getscheduler()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sched_getscheduler(2) */
++static inline abi_long do_freebsd_sched_rr_get_interval(pid_t pid,
++ abi_ulong target_ts_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall sched_rr_get_interval()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset(2) */
++static inline abi_long do_freebsd_cpuset(abi_ulong target_cpuid)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset_setid(2) */
++static inline abi_long do_freebsd_cpuset_setid(void *cpu_env, abi_long arg1,
++ abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset_setid()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset_getid(2) */
++static inline abi_long do_freebsd_cpuset_getid(abi_long arg1, abi_ulong arg2,
++ abi_ulong arg3, abi_ulong arg4, abi_ulong arg5)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset_getid()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset_getaffinity(2) */
++static inline abi_long do_freebsd_cpuset_getaffinity(abi_long arg1,
++ abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5,
++ abi_ulong arg6)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset_getaffinity()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cpuset_setaffinity(2) */
++static inline abi_long do_freebsd_cpuset_setaffinity(abi_long arg1,
++ abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5,
++ abi_ulong arg6)
++{
++
++ qemu_log("qemu: Unsupported syscall cpuset_setaffinity()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* modfnext(2) */
++static inline abi_long do_freebsd_modfnext(abi_long modid)
++{
++
++ qemu_log("qemu: Unsupported syscall modfnext()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* modfind(2) */
++static inline abi_long do_freebsd_modfind(abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall modfind()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldload(2) */
++static inline abi_long do_freebsd_kldload(abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall kldload()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldunload(2) */
++static inline abi_long do_freebsd_kldunload(abi_long fileid)
++{
++
++ qemu_log("qemu: Unsupported syscall kldunload()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldunloadf(2) */
++static inline abi_long do_freebsd_kldunloadf(abi_long fileid, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall kldunloadf()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldfind(2) */
++static inline abi_long do_freebsd_kldfind(abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall kldfind()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldnext(2) */
++static inline abi_long do_freebsd_kldnext(abi_long fileid)
++{
++
++ qemu_log("qemu: Unsupported syscall kldnext()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* kldstat(2) */
++static inline abi_long do_freebsd_kldstat(abi_long fileid,
++ abi_ulong target_stat)
++{
++
++ qemu_log("qemu: Unsupported syscall kldstat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldfirstmod(2) */
++static inline abi_long do_freebsd_kldfirstmod(abi_long fileid)
++{
++
++ qemu_log("qemu: Unsupported syscall kldfirstmod()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* kldsym(2) */
++static inline abi_long do_freebsd_kldsym(abi_long fileid, abi_long cmd,
++ abi_ulong target_data)
++{
++
++ qemu_log("qemu: Unsupported syscall kldsym()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * Resource limits (undocumented except for rctl(8) and rctl.conf(5) )
++ */
++/* rctl_get_racct() */
++static inline abi_long do_freebsd_rctl_get_racct(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_get_racct()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_get_rules() */
++static inline abi_long do_freebsd_rctl_get_rules(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_get_rules()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_add_rule() */
++static inline abi_long do_freebsd_rctl_add_rule(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_add_rule()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_remove_rule() */
++static inline abi_long do_freebsd_rctl_remove_rule(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_remove_rule()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rctl_get_limits() */
++static inline abi_long do_freebsd_rctl_get_limits(abi_ulong target_inbufp,
++ abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen)
++{
++
++ qemu_log("qemu: Unsupported syscall rctl_get_limits()\n");
++ return -TARGET_ENOSYS;
++}
++
++/*
++ * Kernel environment
++ */
++
++/* kenv(2) */
++static inline abi_long do_freebsd_kenv(abi_long what, abi_ulong target_name,
++ abi_ulong target_value, abi_long len)
++{
++
++ qemu_log("qemu: Unsupported syscall kenv()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/*
++ * Mandatory Access Control
++ */
++
++/* __mac_get_proc */
++static inline abi_long do_freebsd___mac_get_proc(abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_proc()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_proc */
++static inline abi_long do_freebsd___mac_set_proc(abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_proc()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/* __mac_get_fd */
++static inline abi_long do_freebsd___mac_get_fd(abi_long fd,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_fd */
++static inline abi_long do_freebsd___mac_set_fd(abi_long fd,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_fd()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_get_file */
++static inline abi_long do_freebsd___mac_get_file(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_file */
++static inline abi_long do_freebsd___mac_set_file(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_file()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_get_link */
++static inline abi_long do_freebsd___mac_get_link(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_get_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* __mac_set_link */
++static inline abi_long do_freebsd___mac_set_link(abi_ulong target_path,
++ abi_ulong target_mac)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_set_link()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* mac_syscall */
++static inline abi_long do_freebsd_mac_syscall(abi_ulong target_policy,
++ abi_long call, abi_ulong target_arg)
++{
++
++ qemu_log("qemu: Unsupported syscall mac_syscall()\n");
++ return -TARGET_ENOSYS;
++}
++
++
++/*
++ * New posix calls
++ */
++/* posix_fallocate(2) */
++static inline abi_long do_freebsd_posix_fallocate(abi_long fd, abi_ulong offset,
++ abi_ulong len)
++{
++
++ qemu_log("qemu: Unsupported syscall posix_fallocate()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* posix_openpt(2) */
++static inline abi_long do_freebsd_posix_openpt(abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall posix_openpt()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* posix_fadvise(2) */
++static inline abi_long do_freebsd_posix_fadvise(abi_long fd, abi_ulong offset,
++ abi_ulong len, abi_long advise)
++{
++
++ qemu_log("qemu: Unsupported syscall posix_fadvise()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* ! __OS_MISC_H_ */
+diff --git a/bsd-user/openbsd/os-proc.c b/bsd-user/openbsd/os-proc.c
+new file mode 100644
+index 0000000..bc11d29
+--- /dev/null
++++ b/bsd-user/openbsd/os-proc.c
+@@ -0,0 +1,11 @@
++/*
++ * XXX To support FreeBSD binaries on NetBSD the following will need to be
++ * emulated.
++ */
++abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
++ abi_ulong guest_envp, int do_fexec)
++{
++
++ qemu_log("qemu: Unsupported %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
+diff --git a/bsd-user/openbsd/os-proc.h b/bsd-user/openbsd/os-proc.h
+new file mode 100644
+index 0000000..9cce719
+--- /dev/null
++++ b/bsd-user/openbsd/os-proc.h
+@@ -0,0 +1,243 @@
++#ifndef __OPENBSD_PROC_H_
++#define __OPENBSD_PROC_H_
++
++/*
++ * XXX To support FreeBSD binaries on OpenBSD these syscalls will need
++ * to be emulated.
++ */
++
++/* execve(2) */
++static inline abi_long do_freebsd_execve(abi_ulong path_or_fd, abi_ulong argp,
++ abi_ulong envp)
++{
++
++ qemu_log("qemu: Unsupported syscall execve()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fexecve(2) */
++static inline abi_long do_freebsd_fexecve(abi_ulong path_or_fd, abi_ulong argp,
++ abi_ulong envp)
++{
++
++ qemu_log("qemu: Unsupported syscall fexecve()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* wait4(2) */
++static inline abi_long do_freebsd_wait4(abi_long arg1, abi_ulong target_status,
++ abi_long arg3, abi_ulong target_rusage)
++{
++
++ qemu_log("qemu: Unsupported syscall wait4()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setloginclass(2) */
++static inline abi_long do_freebsd_setloginclass(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall setloginclass()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getloginclass(2) */
++static inline abi_long do_freebsd_getloginclass(abi_ulong arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall getloginclass()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* pdwait4(2) */
++static inline abi_long do_freebsd_pdwait4(abi_long arg1,
++ abi_ulong target_status, abi_long arg3, abi_ulong target_rusage)
++{
++
++ qemu_log("qemu: Unsupported syscall pdwait4()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* pdgetpid(2) */
++static inline abi_long do_freebsd_pdgetpid(abi_long fd, abi_ulong target_pidp)
++{
++
++ qemu_log("qemu: Unsupported syscall pdgetpid()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* undocumented __setugid */
++static inline abi_long do_freebsd___setugid(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall __setugid()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fork(2) */
++static inline abi_long do_freebsd_fork(void *cpu_env)
++{
++
++ qemu_log("qemu: Unsupported syscall fork()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* vfork(2) */
++static inline abi_long do_freebsd_vfork(void *cpu_env)
++{
++
++ qemu_log("qemu: Unsupported syscall vfork()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* rfork(2) */
++static inline abi_long do_freebsd_rfork(void *cpu_env, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall rfork()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* pdfork(2) */
++static inline abi_long do_freebsd_pdfork(void *cpu_env, abi_ulong arg1,
++ abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall pdfork()\n");
++ return -TARGET_ENOSYS
++}
++
++/* jail(2) */
++static inline abi_long do_freebsd_jail(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall jail()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_attach(2) */
++static inline abi_long do_freebsd_jail_attach(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_attach()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_remove(2) */
++static inline abi_long do_freebsd_jail_remove(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_remove()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_get(2) */
++static inline abi_long do_freebsd_jail_get(abi_ulong arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_get()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* jail_set(2) */
++static inline abi_long do_freebsd_jail_set(abi_ulong arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall jail_set()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_enter(2) */
++static inline abi_long do_freebsd_cap_enter(void)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_enter()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_new(2) */
++static inline abi_long do_freebsd_cap_new(abi_long arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_new()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_getrights(2) */
++static inline abi_long do_freebsd_cap_getrights(abi_long arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_getrights()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* cap_getmode(2) */
++static inline abi_long do_freebsd_cap_getmode(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall cap_getmode()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* audit(2) */
++static inline abi_long do_freebsd_audit(abi_ulong arg1, abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall audit()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* auditon(2) */
++static inline abi_long do_freebsd_auditon(abi_long arg1, abi_ulong arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall auditon()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getaudit(2) */
++static inline abi_long do_freebsd_getaudit(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall getaudit()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setaudit(2) */
++static inline abi_long do_freebsd_setaudit(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall setaudit()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getaudit_addr(2) */
++static inline abi_long do_freebsd_getaudit_addr(abi_ulong arg1,
++ abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall getaudit_addr()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setaudit_addr(2) */
++static inline abi_long do_freebsd_setaudit_addr(abi_ulong arg1,
++ abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall setaudit_addr()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* auditctl(2) */
++static inline abi_long do_freebsd_auditctl(abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall auditctl()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* ! __OPENBSD_PROC_H_ */
+diff --git a/bsd-user/openbsd/os-socket.c b/bsd-user/openbsd/os-socket.c
+new file mode 100644
+index 0000000..183002d
+--- /dev/null
++++ b/bsd-user/openbsd/os-socket.c
+@@ -0,0 +1 @@
++/* XXX OpenBSD socket related helpers */
+diff --git a/bsd-user/openbsd/os-socket.h b/bsd-user/openbsd/os-socket.h
+new file mode 100644
+index 0000000..b8b1e99
+--- /dev/null
++++ b/bsd-user/openbsd/os-socket.h
+@@ -0,0 +1,98 @@
++/*
++ * OpenBSD socket related system call shims
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef __OPENBSD_SOCKET_H_
++#define __OPENBSD_SOCKET_H_
++
++/*
++ * XXX To support FreeBSD binaries on OpenBSD these syscalls will need
++ * to be emulated.
++ */
++
++/* sendmsg(2) */
++static inline abi_long do_freebsd_sendmsg(int fd, abi_ulong target_msg,
++ int flags)
++{
++
++ qemu_log("qemu: Unsupported syscall sendmsg()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* recvmsg(2) */
++static inline abi_long do_freebsd_recvmsg(int fd, abi_ulong target_msg,
++ int flags)
++{
++
++ qemu_log("qemu: Unsupported syscall recvmsg()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setsockopt(2) */
++static inline abi_long do_bsd_setsockopt(int sockfd, int level, int optname,
++ abi_ulong optval_addr, socklen_t optlen)
++{
++
++ qemu_log("qemu: Unsupported syscall setsockopt()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getsockopt(2) */
++static inline abi_long do_bsd_getsockopt(int sockfd, int level, int optname,
++ abi_ulong optval_addr, abi_ulong optlen)
++{
++
++ qemu_log("qemu: Unsupported syscall getsockopt()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* setfib(2) */
++static inline abi_long do_freebsd_setfib(abi_long fib)
++{
++
++ qemu_log("qemu: Unsupported syscall setfib()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sctp_peeloff(2) */
++static inline abi_long do_freebsd_sctp_peeloff(abi_long s, abi_ulong id)
++{
++
++ qemu_log("qemu: Unsupported syscall sctp_peeloff()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sctp_generic_sendmsg(2) */
++static inline abi_long do_freebsd_sctp_generic_sendmsg(abi_long s,
++ abi_ulong target_msg, abi_long msglen, abi_ulong target_to,
++ abi_ulong len, abi_ulong target_sinfo, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall sctp_generic_sendmsg()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sctp_generic_recvmsg(2) */
++static inline abi_long do_freebsd_sctp_generic_recvmsg(abi_long s,
++ abi_ulong target_iov, abi_long iovlen, abi_ulong target_from,
++ abi_ulong fromlen, abi_ulong target_sinfo, abi_ulong target_msgflags)
++{
++
++ qemu_log("qemu: Unsupported syscall sctp_generic_recvmsg()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* !__OPENBSD_SOCKET_H_ */
+diff --git a/bsd-user/openbsd/os-stat.c b/bsd-user/openbsd/os-stat.c
+new file mode 100644
+index 0000000..de4e3f5
+--- /dev/null
++++ b/bsd-user/openbsd/os-stat.c
+@@ -0,0 +1 @@
++/* XXX OpenBSD stat related helpers */
+diff --git a/bsd-user/openbsd/os-stat.h b/bsd-user/openbsd/os-stat.h
+new file mode 100644
+index 0000000..1d3850d
+--- /dev/null
++++ b/bsd-user/openbsd/os-stat.h
+@@ -0,0 +1,176 @@
++/*
++ * OpenBSD stat related system call shims and definitions
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __OPENBSD_STAT_H_
++#define __OPENBSD_STAT_H_
++
++/*
++ * XXX To support FreeBSD binaries on OpenBSD these syscalls will need
++ * to be emulated.
++ */
++
++/* stat(2) */
++static inline abi_long do_freebsd_stat(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall stat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* lstat(2) */
++static inline abi_long do_freebsd_lstat(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall lstat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fstat(2) */
++static inline abi_long do_freebsd_fstat(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall fstat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fstatat(2) */
++static inline abi_long do_freebsd_fstatat(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall fstatat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* undocummented nstat(char *path, struct nstat *ub) syscall */
++static abi_long do_freebsd_nstat(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall nstat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* undocummented nfstat(int fd, struct nstat *sb) syscall */
++static abi_long do_freebsd_nfstat(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall nfstat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* undocummented nlstat(char *path, struct nstat *ub) syscall */
++static abi_long do_freebsd_nlstat(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall nlstat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getfh(2) */
++static abi_long do_freebsd_getfh(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall getfh()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* lgetfh(2) */
++static inline abi_long do_freebsd_lgetfh(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall lgetfh()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fhopen(2) */
++static inline abi_long do_freebsd_fhopen(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall fhopen()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fhstat(2) */
++static inline abi_long do_freebsd_fhstat(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall fhstat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fhstatfs(2) */
++static inline abi_long do_freebsd_fhstatfs(abi_ulong target_fhp_addr,
++ abi_ulong target_stfs_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall fhstatfs()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* statfs(2) */
++static inline abi_long do_freebsd_statfs(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall statfs()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fstatfs(2) */
++static inline abi_long do_freebsd_fstatfs(abi_long fd, abi_ulong target_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall fstatfs()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getfsstat(2) */
++static inline abi_long do_freebsd_getfsstat(abi_ulong target_addr,
++ abi_long bufsize, abi_long flags)
++{
++
++ qemu_log("qemu: Unsupported syscall getfsstat()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getdents(2) */
++static inline abi_long do_freebsd_getdents(abi_long arg1, abi_ulong arg2,
++ abi_long nbytes)
++{
++
++ qemu_log("qemu: Unsupported syscall getdents()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* getdirecentries(2) */
++static inline abi_long do_freebsd_getdirentries(abi_long arg1, abi_ulong arg2,
++ abi_long nbytes, abi_ulong arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall getdirecentries()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* fcntl(2) */
++static inline abi_long do_freebsd_fcntl(abi_long arg1, abi_long arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall fcntl()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* ! __OPENBSD_STAT_H_ */
+diff --git a/bsd-user/openbsd/os-strace.h b/bsd-user/openbsd/os-strace.h
+new file mode 100644
+index 0000000..9161390
+--- /dev/null
++++ b/bsd-user/openbsd/os-strace.h
+@@ -0,0 +1 @@
++/* XXX OpenBSD dependent strace print functions */
+diff --git a/bsd-user/openbsd/os-sys.c b/bsd-user/openbsd/os-sys.c
+new file mode 100644
+index 0000000..30df472
+--- /dev/null
++++ b/bsd-user/openbsd/os-sys.c
+@@ -0,0 +1,46 @@
++/*
++ * OpenBSD sysctl() and sysarch() system call emulation
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++#include <sys/param.h>
++#include <sys/sysctl.h>
++#include <string.h>
++
++#include "qemu.h"
++
++#include "target_arch_sysarch.h"
++#include "target_os_vmparam.h"
++
++
++/* This must be emulated to support FreeBSD target binaries on NetBSD host. */
++
++abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen,
++ abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen)
++{
++
++ qemu_log("qemu: Unsupported syscall __sysctl()\n");
++ return -TARGET_ENOSYS;
++}
++
++/* sysarch() is architecture dependent. */
++abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall sysarch()\n");
++ return -TARGET_ENOSYS;
++}
+diff --git a/bsd-user/openbsd/os-thread.c b/bsd-user/openbsd/os-thread.c
+new file mode 100644
+index 0000000..d125281
+--- /dev/null
++++ b/bsd-user/openbsd/os-thread.c
+@@ -0,0 +1 @@
++/* XXX OpenBSD thread related helpers */
+diff --git a/bsd-user/openbsd/os-thread.h b/bsd-user/openbsd/os-thread.h
+new file mode 100644
+index 0000000..962a769
+--- /dev/null
++++ b/bsd-user/openbsd/os-thread.h
+@@ -0,0 +1,133 @@
++#ifndef __OPENBSD_OS_THREAD_H_
++#define __OPENBSD_OS_THREAD_H_
++
++/*
++ * XXX To support FreeBSD binaries on OpenBSD these syscalls will need to
++ * be emulated.
++ */
++static abi_long do_freebsd_thr_create(CPUArchState *env, abi_ulong target_ctx,
++ abi_ulong target_id, int flags)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_create()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_create(CPUArchState *env, abi_ulong thread_ctx,
++ abi_ulong target_id, int flags)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_create()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_new(CPUArchState *env,
++ abi_ulong target_param_addr, int32_t param_size)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_new()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_self(abi_ulong target_id)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_self()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_exit(CPUArchState *cpu_env, abi_ulong tid_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_exit()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_kill(long id, int sig)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_kill()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_kill2(pid_t pid, long id, int sig)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_kill2()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_suspend(abi_ulong target_ts)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_suspend()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_wake(long tid)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_wake()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_thr_set_name(long tid, abi_ulong target_name)
++{
++
++ qemu_log("qemu: Unsupported syscall thr_set_name()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_rtprio_thread(int function, lwpid_t lwpid,
++ abi_ulong target_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall rtprio_thread()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_getcontext(void *cpu_env, abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall getcontext()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_setcontext(void *cpu_env, abi_ulong arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall setcontext()\n");
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_swapcontext(void *cpu_env, abi_ulong arg1,
++ abi_ulong arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall swapcontext()\n");
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd__umtx_lock(abi_ulong target_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall _umtx_lock()\n");
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd__umtx_unlock(abi_ulong target_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall _umtx_unlock()\n");
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd__umtx_op(abi_ulong obj, int op, abi_ulong val,
++ abi_ulong uaddr, abi_ulong target_ts)
++{
++
++ qemu_log("qemu: Unsupported syscall _umtx_op()\n");
++ return -TARGET_ENOSYS;
++}
++
++#endif /* ! __OPENBSD_OS_THREAD_H_ */
+diff --git a/bsd-user/openbsd/os-time.c b/bsd-user/openbsd/os-time.c
+new file mode 100644
+index 0000000..accd886
+--- /dev/null
++++ b/bsd-user/openbsd/os-time.c
+@@ -0,0 +1 @@
++/* XXX OpenBSD time related helpers */
+diff --git a/bsd-user/openbsd/os-time.h b/bsd-user/openbsd/os-time.h
+new file mode 100644
+index 0000000..fc444bb
+--- /dev/null
++++ b/bsd-user/openbsd/os-time.h
+@@ -0,0 +1,179 @@
++#ifndef __OPENBSD_OS_TIME_H_
++#define __OPENBSD_OS_TIME_H_
++
++/*
++ * XXX To support FreeBSD binaries on OpenBSD these syscalls will need to
++ * be emulated.
++ */
++static inline abi_long do_freebsd_nanosleep(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_clock_gettime(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_clock_settime(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_clock_getres(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_gettimeofday(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_settimeofday(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_adjtime(abi_ulong target_delta_addr,
++ abi_ulong target_old_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_ntp_adjtime(abi_ulong target_tx_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static abi_long do_freebsd_ntp_gettime(abi_ulong target_ntv_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_utimes(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_lutimes(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_futimes(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_futimesat(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_ktimer_create(abi_long arg1, abi_long arg2,
++ abi_long arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_ktimer_delete(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_ktimer_settime(abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_ktimer_gettime(abi_long arg1, abi_long arg2)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_ktimer_getoverrun(abi_long arg1)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_select(int n, abi_ulong rfd_addr,
++ abi_ulong wfd_addr, abi_ulong efd_addr, abi_ulong target_tv_addr)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++
++static inline 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)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_kqueue(void)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_kevent(abi_long arg1, abi_ulong arg2,
++ abi_long arg3, abi_ulong arg4, abi_long arg5, abi_long arg6)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++static inline abi_long do_freebsd_sigtimedwait(abi_ulong arg1, abi_ulong arg2,
++ abi_ulong arg3)
++{
++
++ qemu_log("qemu: Unsupported syscall %s\n", __func__);
++ return -TARGET_ENOSYS;
++}
++
++#endif /* ! __OPENBSD_OS_TIME_H_ */
+diff --git a/bsd-user/openbsd/qemu-os.h b/bsd-user/openbsd/qemu-os.h
+new file mode 100644
+index 0000000..f4ad3be
+--- /dev/null
++++ b/bsd-user/openbsd/qemu-os.h
+@@ -0,0 +1 @@
++/* OpenBSD conversion extern declarations */
+diff --git a/bsd-user/openbsd/target_os_elf.h b/bsd-user/openbsd/target_os_elf.h
+new file mode 100644
+index 0000000..978d944
+--- /dev/null
++++ b/bsd-user/openbsd/target_os_elf.h
+@@ -0,0 +1,226 @@
++/*
++ * openbsd ELF definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_OS_ELF_H_
++#define _TARGET_OS_ELF_H_
++
++#include "target_arch_elf.h"
++#include "elf.h"
++
++/* from personality.h */
++
++/*
++ * Flags for bug emulation.
++ *
++ * These occupy the top three bytes.
++ */
++enum {
++ ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA
++ space */
++ FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs
++ point to descriptors
++ (signal handling) */
++ MMAP_PAGE_ZERO = 0x0100000,
++ ADDR_COMPAT_LAYOUT = 0x0200000,
++ READ_IMPLIES_EXEC = 0x0400000,
++ ADDR_LIMIT_32BIT = 0x0800000,
++ SHORT_INODE = 0x1000000,
++ WHOLE_SECONDS = 0x2000000,
++ STICKY_TIMEOUTS = 0x4000000,
++ ADDR_LIMIT_3GB = 0x8000000,
++};
++
++/*
++ * Personality types.
++ *
++ * These go in the low byte. Avoid using the top bit, it will
++ * conflict with error returns.
++ */
++enum {
++ PER_LINUX = 0x0000,
++ PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
++ PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
++ PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
++ PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
++ PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS |
++ WHOLE_SECONDS | SHORT_INODE,
++ PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
++ PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
++ PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
++ PER_BSD = 0x0006,
++ PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
++ PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
++ PER_LINUX32 = 0x0008,
++ PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
++ PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
++ PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
++ PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
++ PER_RISCOS = 0x000c,
++ PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
++ PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
++ PER_OSF4 = 0x000f, /* OSF/1 v4 */
++ PER_HPUX = 0x0010,
++ PER_MASK = 0x00ff,
++};
++
++/*
++ * Return the base personality without flags.
++ */
++#define personality(pers) (pers & PER_MASK)
++
++/* this flag is uneffective under linux too, should be deleted */
++#ifndef MAP_DENYWRITE
++#define MAP_DENYWRITE 0
++#endif
++
++/* should probably go in elf.h */
++#ifndef ELIBBAD
++#define ELIBBAD 80
++#endif
++
++#ifndef ELF_PLATFORM
++#define ELF_PLATFORM (NULL)
++#endif
++
++#ifndef ELF_HWCAP
++#define ELF_HWCAP 0
++#endif
++
++#ifdef TARGET_ABI32
++#undef ELF_CLASS
++#define ELF_CLASS ELFCLASS32
++#undef bswaptls
++#define bswaptls(ptr) bswap32s(ptr)
++#endif
++
++struct exec
++{
++ unsigned int a_info; /* Use macros N_MAGIC, etc for access */
++ unsigned int a_text; /* length of text, in bytes */
++ unsigned int a_data; /* length of data, in bytes */
++ unsigned int a_bss; /* length of uninitialized data area, in bytes */
++ unsigned int a_syms; /* length of symbol table data in file, in bytes */
++ unsigned int a_entry; /* start address */
++ unsigned int a_trsize; /* length of relocation info for text, in bytes */
++ unsigned int a_drsize; /* length of relocation info for data, in bytes */
++};
++
++
++#define N_MAGIC(exec) ((exec).a_info & 0xffff)
++#define OMAGIC 0407
++#define NMAGIC 0410
++#define ZMAGIC 0413
++#define QMAGIC 0314
++
++/* max code+data+bss space allocated to elf interpreter */
++#define INTERP_MAP_SIZE (32 * 1024 * 1024)
++
++/* max code+data+bss+brk space allocated to ET_DYN executables */
++#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
++
++/* Necessary parameters */
++#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
++#define TARGET_ELF_PAGESTART(_v) ((_v) & \
++ ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
++#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
++
++#define INTERPRETER_NONE 0
++#define INTERPRETER_AOUT 1
++#define INTERPRETER_ELF 2
++
++#define DLINFO_ITEMS 12
++
++static abi_ulong target_create_elf_tables(abi_ulong p, int argc, int envc,
++ struct elfhdr * exec,
++ abi_ulong load_addr,
++ abi_ulong load_bias,
++ abi_ulong interp_load_addr, int ibcs,
++ struct image_info *info)
++{
++ abi_ulong sp;
++ int size;
++ abi_ulong u_platform;
++ const char *k_platform;
++ const int n = sizeof(elf_addr_t);
++
++ sp = p;
++ u_platform = 0;
++ k_platform = ELF_PLATFORM;
++ if (k_platform) {
++ size_t len = strlen(k_platform) + 1;
++ sp -= (len + n - 1) & ~(n - 1);
++ u_platform = sp;
++ /* FIXME - check return value of memcpy_to_target() for failure */
++ memcpy_to_target(sp, k_platform, len);
++ }
++ /*
++ * Force 16 byte _final_ alignment here for generality.
++ */
++ sp = sp &~ (abi_ulong)15;
++ size = (DLINFO_ITEMS + 1) * 2;
++ if (k_platform)
++ size += 2;
++#ifdef DLINFO_ARCH_ITEMS
++ size += DLINFO_ARCH_ITEMS * 2;
++#endif
++ size += envc + argc + 2;
++ size += (!ibcs ? 3 : 1); /* argc itself */
++ size *= n;
++ if (size & 15)
++ sp -= 16 - (size & 15);
++
++ /* This is correct because Linux defines
++ * elf_addr_t as Elf32_Off / Elf64_Off
++ */
++#define NEW_AUX_ENT(id, val) do { \
++ sp -= n; put_user_ual(val, sp); \
++ sp -= n; put_user_ual(id, sp); \
++ } while(0)
++
++ NEW_AUX_ENT (AT_NULL, 0);
++
++ /* There must be exactly DLINFO_ITEMS entries here. */
++ NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
++ NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
++ NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
++ NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
++ NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
++ NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
++ NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
++ NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
++ NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
++ NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
++ 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));
++ if (k_platform)
++ NEW_AUX_ENT(AT_PLATFORM, u_platform);
++#ifdef ARCH_DLINFO
++ /*
++ * ARCH_DLINFO must come last so platform specific code can enforce
++ * special alignment requirements on the AUXV if necessary (eg. PPC).
++ */
++ ARCH_DLINFO;
++#endif
++#undef NEW_AUX_ENT
++
++ sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
++ return sp;
++}
++
++#endif /* _TARGET_OS_ELF_H_ */
+diff --git a/bsd-user/openbsd/target_os_siginfo.h b/bsd-user/openbsd/target_os_siginfo.h
+new file mode 100644
+index 0000000..baf646a
+--- /dev/null
++++ b/bsd-user/openbsd/target_os_siginfo.h
+@@ -0,0 +1,82 @@
++#ifndef _TARGET_OS_SIGINFO_H_
++#define _TARGET_OS_SIGINFO_H_
++
++#define TARGET_NSIG 32 /* counting 0; could be 33 (mask is 1-32) */
++#define TARGET_NSIG_BPW (sizeof(uint32_t) * 8)
++#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
++
++/* 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;
++};
++
++/* Compare to sys/siginfo.h */
++typedef union target_sigval {
++ int sival_int;
++ abi_ulong sival_ptr;
++} target_sigval_t;
++
++struct target_ksiginfo {
++ int32_t _signo;
++ int32_t _code;
++ int32_t _errno;
++#if TARGET_ABI_BITS == 64
++ int32_t _pad;
++#endif
++ union {
++ struct {
++ int32_t _pid;
++ int32_t _uid;
++ target_sigval_t _value;
++ } _rt;
++
++ struct {
++ int32_t _pid;
++ int32_t _uid;
++ int32_t _struct;
++ /* clock_t _utime; */
++ /* clock_t _stime; */
++ } _child;
++
++ struct {
++ abi_ulong _addr;
++ int32_t _trap;
++ } _fault;
++
++ struct {
++ long _band;
++ int _fd;
++ } _poll;
++ } _reason;
++};
++
++typedef union target_siginfo {
++ int8_t si_pad[128];
++ struct target_ksiginfo _info;
++} target_siginfo_t;
++
++#define target_si_signo _info._signo
++#define target_si_code _info._code
++#define target_si_errno _info._errno
++#define target_si_addr _info._reason._fault._addr
++
++#define TARGET_SEGV_MAPERR 1
++#define TARGET_SEGV_ACCERR 2
++
++#define TARGET_TRAP_BRKPT 1
++#define TARGET_TRAP_TRACE 2
++
++
++#endif /* ! _TARGET_OS_SIGINFO_H_ */
+diff --git a/bsd-user/openbsd/target_os_signal.h b/bsd-user/openbsd/target_os_signal.h
+new file mode 100644
+index 0000000..d39a26f
+--- /dev/null
++++ b/bsd-user/openbsd/target_os_signal.h
+@@ -0,0 +1,70 @@
++#ifndef _TARGET_OS_SIGNAL_H_
++#define _TARGET_OS_SIGNAL_H_
++
++#include "target_os_siginfo.h"
++#include "target_arch_signal.h"
++
++#define TARGET_SIGHUP 1 /* hangup */
++#define TARGET_SIGINT 2 /* interrupt */
++#define TARGET_SIGQUIT 3 /* quit */
++#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught) */
++#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
++#define TARGET_SIGABRT 6 /* abort() */
++#define TARGET_SIGIOT SIGABRT /* compatibility */
++#define TARGET_SIGEMT 7 /* EMT instruction */
++#define TARGET_SIGFPE 8 /* floating point exception */
++#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
++#define TARGET_SIGBUS 10 /* bus error */
++#define TARGET_SIGSEGV 11 /* segmentation violation */
++#define TARGET_SIGSYS 12 /* bad argument to system call */
++#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
++#define TARGET_SIGALRM 14 /* alarm clock */
++#define TARGET_SIGTERM 15 /* software termination signal from kill */
++#define TARGET_SIGURG 16 /* urgent condition on IO channel */
++#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
++#define TARGET_SIGTSTP 18 /* stop signal from tty */
++#define TARGET_SIGCONT 19 /* continue a stopped process */
++#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
++#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
++#define TARGET_SIGTTOU 22 /* like TTIN for output if
++ (tp->t_local&LTOSTOP) */
++#define TARGET_SIGIO 23 /* input/output possible signal */
++#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
++#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
++#define TARGET_SIGVTALRM 26 /* virtual time alarm */
++#define TARGET_SIGPROF 27 /* profiling time alarm */
++#define TARGET_SIGWINCH 28 /* window size changes */
++#define TARGET_SIGINFO 29 /* information request */
++#define TARGET_SIGUSR1 30 /* user defined signal 1 */
++#define TARGET_SIGUSR2 31 /* user defined signal 2 */
++
++/*
++ * 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_SA_ONSTACK 0x0001 /* take signal on signal stack */
++#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
++#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
++#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering */
++#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1) */
++#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
++#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
++#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
++
++/*
++ * Flags for sigprocmask:
++ */
++#define TARGET_SIG_BLOCK 1 /* block specified signal set */
++#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
++#define TARGET_SIG_SETMASK 3 /* set specified signal set */
++
++#define TARGET_BADSIG SIG_ERR
++
++#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
++#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack */
++
++#endif /* !_TARGET_OS_SIGNAL_H_ */
+diff --git a/bsd-user/openbsd/target_os_stack.h b/bsd-user/openbsd/target_os_stack.h
+new file mode 100644
+index 0000000..1a26c3f
+--- /dev/null
++++ b/bsd-user/openbsd/target_os_stack.h
+@@ -0,0 +1,33 @@
++#ifndef _TARGET_OS_STACK_H_
++#define _TARGET_OS_STACK_H_
++
++#include "target_arch_sigtramp.h"
++
++static inline int setup_initial_stack(struct bsd_binprm *bprm, abi_ulong *p)
++{
++ int i;
++ abi_ulong stack_base;
++
++ stack_base = (target_stkbas + target_stksiz) -
++ MAX_ARG_PAGES * TARGET_PAGE_SIZE;
++ if (p) {
++ *p = stack_base;
++ }
++
++ for (i = 0; i < MAX_ARG_PAGES; i++) {
++ if (bprm->page[i]) {
++ info->rss++;
++ if (!memcpy_to_target(stack_base, bprm->page[i],
++ TARGET_PAGE_SIZE)) {
++ errno = EFAULT;
++ return -1;
++ }
++ g_free(bprm->page[i]);
++ }
++ stack_base += TARGET_PAGE_SIZE;
++ }
++
++ return 0;
++}
++
++#endif /* !_TARGET_OS_STACK_H_ */
+diff --git a/bsd-user/openbsd/target_os_thread.h b/bsd-user/openbsd/target_os_thread.h
+new file mode 100644
+index 0000000..519aad8
+--- /dev/null
++++ b/bsd-user/openbsd/target_os_thread.h
+@@ -0,0 +1,6 @@
++#ifndef _TARGET_OS_THREAD_H_
++#define _TARGET_OS_THREAD_H_
++
++#include "target_arch_thread.h"
++
++#endif /* !_TARGET_OS_THREAD_H_ */
+diff --git a/bsd-user/qemu-bsd.h b/bsd-user/qemu-bsd.h
+new file mode 100644
+index 0000000..771245d
+--- /dev/null
++++ b/bsd-user/qemu-bsd.h
+@@ -0,0 +1,79 @@
++/*
++ * BSD conversion extern declarations
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _QEMU_BSD_H_
++#define _QEMU_BSD_H_
++
++#include <sys/types.h>
++#include <sys/ipc.h>
++#include <sys/msg.h>
++#include <sys/resource.h>
++#include <sys/sem.h>
++#include <sys/shm.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <sys/uuid.h>
++#include <sys/wait.h>
++#include <netinet/in.h>
++
++/* bsd-mem.c */
++abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
++ abi_ulong target_addr);
++abi_long host_to_target_ipc_perm(abi_ulong target_addr,
++ struct ipc_perm *host_ip);
++abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
++ abi_ulong target_addr);
++abi_long host_to_target_shmid_ds(abi_ulong target_addr,
++ struct shmid_ds *host_sd);
++
++/* bsd-proc.c */
++int target_to_host_resource(int code);
++rlim_t target_to_host_rlim(abi_ulong target_rlim);
++abi_ulong host_to_target_rlim(rlim_t rlim);
++abi_long host_to_target_rusage(abi_ulong target_addr,
++ const struct rusage *rusage);
++int host_to_target_waitstatus(int status);
++
++/* bsd-socket.c */
++abi_long target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
++ socklen_t len);
++abi_long host_to_target_sockaddr(abi_ulong target_addr, struct sockaddr *addr,
++ socklen_t len);
++abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, abi_ulong target_addr,
++ socklen_t len);
++
++/* bsd-misc.c */
++abi_long host_to_target_uuid(abi_ulong target_addr, struct uuid *host_uuid);
++
++abi_long target_to_host_semarray(int semid, unsigned short **host_array,
++ abi_ulong target_addr);
++abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
++ unsigned short **host_array);
++
++abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
++ abi_ulong target_addr);
++abi_long host_to_target_semid_ds(abi_ulong target_addr,
++ struct semid_ds *host_sd);
++
++abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
++ abi_ulong target_addr);
++abi_long host_to_target_msqid_ds(abi_ulong target_addr,
++ struct msqid_ds *host_md);
++
++#endif /* !_QEMU_BSD_H_ */
+diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
+index ddc74ed..10d0fc4 100644
+--- a/bsd-user/qemu.h
++++ b/bsd-user/qemu.h
+@@ -1,3 +1,19 @@
++/*
++ * qemu bsd user mode definition
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
+ #ifndef QEMU_H
+ #define QEMU_H
+
+@@ -20,16 +36,14 @@ enum BSDType {
+ };
+ extern enum BSDType bsd_type;
+
++#include "exec/user/thunk.h"
+ #include "syscall_defs.h"
+ #include "syscall.h"
+-#include "target_signal.h"
++#include "target_os_vmparam.h"
++#include "target_os_signal.h"
+ #include "exec/gdbstub.h"
+
+-#if defined(CONFIG_USE_NPTL)
+ #define THREAD __thread
+-#else
+-#define THREAD
+-#endif
+
+ /* This struct is used to hold certain information about the image.
+ * Basically, it replicates in user space what would be certain
+@@ -50,21 +64,23 @@ struct image_info {
+ abi_ulong entry;
+ abi_ulong code_offset;
+ abi_ulong data_offset;
++ abi_ulong arg_start;
++ abi_ulong arg_end;
+ int personality;
+ };
+
+ #define MAX_SIGQUEUE_SIZE 1024
+
+-struct sigqueue {
+- struct sigqueue *next;
+- //target_siginfo_t info;
++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
+- first signal, we put it here */
++ struct qemu_sigqueue *first;
++ struct qemu_sigqueue info; /* in order to always have memory for the
++ first signal, we put it here */
+ };
+
+ /* NOTE: we force a big alignment so that the stack stored after is
+@@ -72,17 +88,28 @@ struct emulated_sigtable {
+ typedef struct TaskState {
+ struct TaskState *next;
+ int used; /* non zero if used */
++#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;
++ 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 */
+- 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];
+ } __attribute__((aligned(16))) TaskState;
+
+ void init_task_state(TaskState *ts);
++void stop_all_tasks(void);
+ extern const char *qemu_uname_release;
+ #if defined(CONFIG_USE_GUEST_BASE)
+ extern unsigned long mmap_min_addr;
+@@ -100,7 +127,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;
+@@ -109,19 +136,23 @@ struct linux_binprm {
+ int argc, envc;
+ char **argv;
+ char **envp;
+- char * filename; /* Name of binary */
++ char *filename; /* (Given) Name of binary */
++ char *fullpath; /* Full path of binary */
++ int (*core_dump)(int, const CPUArchState *);
+ };
+
+ 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);
++int loader_exec(const char *filename, char **argv, char **envp,
++ struct target_pt_regs *regs, struct image_info *infop,
++ struct bsd_binprm *bprm);
+
+-int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+- struct image_info * info);
+-int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
+- struct image_info * info);
++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);
+
+ abi_long memcpy_to_target(abi_ulong dest, const void *src,
+ unsigned long len);
+@@ -149,6 +180,16 @@ void fork_end(int child);
+ #include "qemu/log.h"
+
+ /* strace.c */
++struct syscallname {
++ int nr;
++ const char *name;
++ const char *format;
++ void (*call)(const struct syscallname *,
++ abi_long, abi_long, abi_long,
++ abi_long, abi_long, abi_long);
++ void (*result)(const struct syscallname *, abi_long);
++};
++
+ void
+ print_freebsd_syscall(int num,
+ abi_long arg1, abi_long arg2, abi_long arg3,
+@@ -169,17 +210,24 @@ 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);
++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);
++long do_sigreturn(CPUArchState *env, abi_ulong addr);
+ long do_rt_sigreturn(CPUArchState *env);
+ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
++int do_sigaction(int sig, const struct target_sigaction *act,
++ struct target_sigaction *oact);
++void QEMU_NORETURN force_sig(int target_sig);
+
+ /* mmap.c */
+ int target_mprotect(abi_ulong start, abi_ulong len, int prot);
+ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+- int flags, int fd, abi_ulong offset);
++ int flags, int fd, off_t offset);
+ int target_munmap(abi_ulong start, abi_ulong len);
+ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
+ abi_ulong new_size, unsigned long flags,
+@@ -188,15 +236,73 @@ int target_msync(abi_ulong start, abi_ulong len, int flags);
+ extern unsigned long last_brk;
+ void mmap_lock(void);
+ void mmap_unlock(void);
++abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
+ void cpu_list_lock(void);
+ void cpu_list_unlock(void);
+-#if defined(CONFIG_USE_NPTL)
+ void mmap_fork_start(void);
+ void mmap_fork_end(int child);
+-#endif
+
+ /* main.c */
+-extern unsigned long x86_stack_size;
++extern unsigned long target_maxtsiz;
++extern unsigned long target_dfldsiz;
++extern unsigned long target_maxdsiz;
++extern unsigned long target_dflssiz;
++extern unsigned long target_maxssiz;
++extern unsigned long target_sgrowsiz;
++extern char qemu_proc_pathname[];
++void start_exclusive(void);
++void end_exclusive(void);
++void cpu_exec_start(CPUState *cpu);
++void cpu_exec_end(CPUState *cpu);
++
++/* syscall.c */
++abi_long get_errno(abi_long ret);
++int is_error(abi_long ret);
++int host_to_target_errno(int err);
++
++/* os-proc.c */
++abi_long freebsd_exec_common(abi_ulong path_or_fd, abi_ulong guest_argp,
++ abi_ulong guest_envp, int do_fexec);
++
++/* os-sys.c */
++abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen,
++ abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen);
++abi_long do_freebsd_sysarch(void *cpu_env, abi_long arg1, abi_long arg2);
++
++/* os-thread.c */
++extern pthread_mutex_t *new_freebsd_thread_lock_ptr;
++void *new_freebsd_thread_start(void *arg);
++abi_long freebsd_lock_umtx(abi_ulong target_addr, abi_long tid,
++ struct timespec *timeout);
++abi_long freebsd_unlock_umtx(abi_ulong target_addr, abi_long id);
++abi_long freebsd_umtx_wait(abi_ulong targ_addr, abi_ulong id,
++ struct timespec *ts);
++abi_long freebsd_umtx_wake(abi_ulong target_addr, uint32_t n_wake);
++abi_long freebsd_umtx_mutex_wake(abi_ulong target_addr, abi_long val);
++abi_long freebsd_umtx_wait_uint(abi_ulong obj, uint32_t val,
++ struct timespec *timeout);
++abi_long freebsd_umtx_wait_uint_private(abi_ulong obj, uint32_t val,
++ struct timespec *timeout);
++abi_long freebsd_umtx_wake_private(abi_ulong obj, uint32_t val);
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
++abi_long freebsd_umtx_nwake_private(abi_ulong obj, uint32_t val);
++abi_long freebsd_umtx_mutex_wake2(abi_ulong obj, uint32_t val);
++abi_long freebsd_umtx_sem_wait(abi_ulong obj, struct timespec *timeout);
++abi_long freebsd_umtx_sem_wake(abi_ulong obj, uint32_t val);
++#endif
++abi_long freebsd_lock_umutex(abi_ulong target_addr, uint32_t id,
++ struct timespec *ts, int mode);
++abi_long freebsd_unlock_umutex(abi_ulong target_addr, uint32_t id);
++abi_long freebsd_cv_wait(abi_ulong target_ucond_addr,
++ abi_ulong target_umtx_addr, struct timespec *ts, int wflags);
++abi_long freebsd_cv_signal(abi_ulong target_ucond_addr);
++abi_long freebsd_cv_broadcast(abi_ulong target_ucond_addr);
++abi_long freebsd_rw_rdlock(abi_ulong target_addr, long fflag,
++ struct timespec *ts);
++abi_long freebsd_rw_wrlock(abi_ulong target_addr, long fflag,
++ struct timespec *ts);
++abi_long freebsd_rw_unlock(abi_ulong target_addr);
++
+
+ /* user access */
+
+@@ -387,8 +493,42 @@ static inline void *lock_user_string(abi_ulong guest_addr)
+ #define unlock_user_struct(host_ptr, guest_addr, copy) \
+ unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0)
+
+-#if defined(CONFIG_USE_NPTL)
+-#include <pthread.h>
++#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
++}
++#else /* TARGET_ABI_BITS != 32 */
++static inline uint64_t
++target_offset64(uint64_t word0, uint64_t word1)
++{
++ return word0;
++}
++#endif /* TARGET_ABI_BITS != 32 */
++
++/* 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
++
++#include <pthread.h>
+
+ #endif /* QEMU_H */
+diff --git a/bsd-user/signal.c b/bsd-user/signal.c
+index 445f69e..3619b00 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) 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
+@@ -23,16 +24,920 @@
+ #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
+
++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[TARGET_NSIG] = {
++ [SIGHUP] = TARGET_SIGHUP,
++ [SIGINT] = TARGET_SIGINT,
++ [SIGQUIT] = TARGET_SIGQUIT,
++ [SIGILL] = TARGET_SIGILL,
++ [SIGTRAP] = TARGET_SIGTRAP,
++ [SIGABRT] = TARGET_SIGABRT,
++ [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 + 3] = 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[TARGET_NSIG];
++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);
++
++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 < 0 || sig >= TARGET_NSIG) {
++ return sig;
++ }
++
++ return host_to_target_signal_table[sig];
++}
++
++int target_to_host_signal(int sig)
++{
++
++ if (sig >= TARGET_NSIG) {
++ return sig;
++ }
++
++ return target_to_host_signal_table[sig];
++}
++
++static inline void target_sigemptyset(target_sigset_t *set)
++{
++
++ memset(set, 0, sizeof(*set));
++}
++
++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, code;
++
++ sig = host_to_target_signal(info->si_signo);
++ /* XXX should have host_to_target_si_code() */
++ code = tswap32(info->si_code);
++ 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
++ if (SIGPOLL == sig) {
++ tinfo->_reason._poll._band = info->_reason._poll._band;
++ }
++#endif
++ if (SI_TIMER == code) {
++ 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, 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);
++ 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
++ if (SIGPOLL == sig) {
++ tinfo->_reason._poll._band = tswap32(info->_reason._poll._band);
++ }
++#endif
++ if (SI_TIMER == code) {
++ 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 qemu_sigqueue *alloc_sigqueue(CPUArchState *env)
++{
++ TaskState *ts = env->opaque;
++ struct qemu_sigqueue *q = ts->first_free;
++
++ if (!q) {
++ return NULL;
++ }
++ ts->first_free = q->next;
++ return q;
++}
++
++static inline void free_sigqueue(CPUArchState *env, struct qemu_sigqueue *q)
++{
++
++ TaskState *ts = env->opaque;
++ q->next = ts->first_free;
++ ts->first_free = q;
++}
++
++/* Abort execution with signal. */
++void QEMU_NORETURN force_sig(int target_sig)
++{
++ CPUArchState *env = thread_cpu->env_ptr;
++ TaskState *ts = (TaskState *)env->opaque;
++ int core_dumped = 0;
++ int host_sig;
++ struct sigaction act;
++
++ host_sig = target_to_host_signal(target_sig);
++ gdb_signalled(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, 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;
++ setrlimit(RLIMIT_CORE, &nodump);
++ (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 qemu_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)
++{
++ CPUArchState *env = thread_cpu->env_ptr;
++ 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 < 0x10000) {
++ 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(env, sig, &tinfo) == 1) {
++ /* Interrupt the virtual CPU as soon as possible. */
++ cpu_exit(thread_cpu);
++ }
++}
++
++/* 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_flags = SA_SIGINFO;
++ 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;
++}
++
++static inline abi_ulong get_sigframe(struct target_sigaction *ka,
++ CPUArchState *regs, size_t frame_size)
++{
++ abi_ulong sp;
++
++ /* Use default user stack */
++ 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;
++ }
++
++#if defined(TARGET_MIPS) || defined(TARGET_ARM)
++ return (sp - frame_size) & ~7;
++#else
++ return sp - frame_size;
++#endif
++}
++
++/* compare to mips/mips/pm_machdep.c and 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, CPUArchState *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;
++ }
++
++ 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;
++#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])) {
++ 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
++
++ }
++
++ if (set_sigtramp_args(regs, sig, frame, frame_addr, ka)) {
++ goto give_sigsegv;
++ }
++
++ unlock_user_struct(frame, frame_addr, 1);
++ return;
++
++give_sigsegv:
++ unlock_user_struct(frame, frame_addr, 1);
++ force_sig(TARGET_SIGSEGV);
++}
++
++static int reset_signal_mask(target_ucontext_t *ucontext)
++{
++ int i;
++ sigset_t blocked;
++ target_sigset_t target_set;
++
++ 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);
++
++ return 0;
++}
++
++long do_sigreturn(CPUArchState *regs, abi_ulong addr)
++{
++ long ret;
++ abi_ulong target_ucontext;
++ target_ucontext_t *ucontext = NULL;
++
++ /* Get the target ucontext address from the stack frame */
++ ret = get_ucontext_sigreturn(regs, addr, &target_ucontext);
++ if (is_error(ret)) {
++ return ret;
++ }
++ if (!lock_user_struct(VERIFY_READ, ucontext, target_ucontext, 0)) {
++ goto badframe;
++ }
++
++ /* Set the register state back to before the signal. */
++ if (set_mcontext(regs, &ucontext->uc_mcontext, 1)) {
++ goto badframe;
++ }
++
++ /* And reset the signal mask. */
++ if (reset_signal_mask(ucontext)) {
++ goto badframe;
++ }
++
++ unlock_user_struct(ucontext, target_ucontext, 0);
++ return -TARGET_EJUSTRETURN;
++
++badframe:
++ if (ucontext != NULL) {
++ unlock_user_struct(ucontext, target_ucontext, 0);
++ }
++ force_sig(TARGET_SIGSEGV);
++ return -TARGET_EFAULT;
++}
++
+ 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 < TARGET_NSIG; i++) {
++ if (host_to_target_signal_table[i] == 0) {
++ host_to_target_signal_table[i] = i;
++ }
++ }
++ for (i = 1; i < TARGET_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;
++ act.sa_flags = SA_SIGINFO;
++
++ 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)
+ {
++ CPUState *cpu = ENV_GET_CPU(cpu_env);
++ 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 qemu_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, 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 /* not yet */
++#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 /* not yet */
++
++ code = q->info.si_code;
++ /* prepare the stack frame of the virtual CPU */
++ if (sa->sa_flags & TARGET_SA_SIGINFO) {
++ tswap_siginfo(&tinfo, &q->info);
++ setup_frame(sig, code, sa, &target_old_set, &tinfo, 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;
++ }
++ }
++ if (q != &k->info) {
++ free_sigqueue(cpu_env, q);
++ }
+ }
+diff --git a/bsd-user/sparc/syscall.h b/bsd-user/sparc/syscall.h
+index 5a9bb7e..3a5b1e2 100644
+--- a/bsd-user/sparc/syscall.h
++++ b/bsd-user/sparc/syscall.h
+@@ -1,3 +1,23 @@
++/*
++ * sparc dependent system call definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _SPARC_SYSCALL_H_
++#define _SPARC_SYSCALL_H_
++
+ struct target_pt_regs {
+ abi_ulong psr;
+ abi_ulong pc;
+@@ -6,4 +26,11 @@ struct target_pt_regs {
+ abi_ulong u_regs[16];
+ };
+
+-#define UNAME_MACHINE "sun4"
++#define UNAME_MACHINE "sun4"
++#define TARGET_HW_MACHINE "sparc"
++#define TARGET_HW_MACHINE_ARCH "sparc"
++
++#define TARGET_SPARC_UTRAP_INSTALL 1
++#define TARGET_SPARC_SIGTRAMP_INSTALL 2
++
++#endif /* ! _SPARC_SYSCALL_H_ */
+diff --git a/bsd-user/sparc/target_arch.h b/bsd-user/sparc/target_arch.h
+new file mode 100644
+index 0000000..5ee479b
+--- /dev/null
++++ b/bsd-user/sparc/target_arch.h
+@@ -0,0 +1,11 @@
++
++#ifndef _TARGET_ARCH_H_
++#define _TARGET_ARCH_H_
++
++void bsd_sparc_save_window(CPUSPARCState *env);
++void bsd_sparc_restore_window(CPUSPARCState *env);
++void bsd_sparc_flush_windows(CPUSPARCState *env);
++
++#define target_cpu_set_tls(env, newtls)
++
++#endif /* ! _TARGET_ARCH_H_ */
+diff --git a/bsd-user/sparc/target_arch_cpu.c b/bsd-user/sparc/target_arch_cpu.c
+new file mode 100644
+index 0000000..0af5c7e
+--- /dev/null
++++ b/bsd-user/sparc/target_arch_cpu.c
+@@ -0,0 +1,113 @@
++/*
++ * sparc cpu related code
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++
++#include "cpu.h"
++#include "qemu.h"
++
++#include "target_arch.h"
++
++/* #define DEBUG_WIN */
++/* WARNING: dealing with register windows _is_ complicated. More info
++ can be found at http://www.sics.se/~psm/sparcstack.html */
++static int get_reg_index(CPUSPARCState *env, int cwp, int index)
++{
++ index = (index + cwp * 16) % (16 * env->nwindows);
++ /* wrap handling : if cwp is on the last window, then we use the
++ registers 'after' the end */
++ if (index < 8 && env->cwp == env->nwindows - 1) {
++ index += 16 * env->nwindows;
++ }
++ return index;
++}
++
++/* save the register window 'cwp1' */
++static void save_window_offset(CPUSPARCState *env, int cwp1)
++{
++ unsigned int i;
++ abi_ulong sp_ptr;
++
++ sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
++#if defined(DEBUG_WIN)
++ printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
++ sp_ptr, cwp1);
++#endif
++ for (i = 0; i < 16; i++) {
++ /* FIXME - what to do if put_user() fails? */
++ put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
++ sp_ptr += sizeof(abi_ulong);
++ }
++}
++
++void bsd_sparc_save_window(CPUSPARCState *env)
++{
++ unsigned int new_wim;
++
++ new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
++ ((1LL << env->nwindows) - 1);
++ save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
++ env->wim = new_wim;
++}
++
++void bsd_sparc_restore_window(CPUSPARCState *env)
++{
++ unsigned int new_wim;
++ unsigned int i, cwp1;
++ abi_ulong sp_ptr;
++
++ new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) &
++ ((1LL << env->nwindows) - 1);
++
++ /* restore the invalid window */
++ cwp1 = cpu_cwp_inc(env, env->cwp + 1);
++ sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
++#if defined(DEBUG_WIN)
++ printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
++ sp_ptr, cwp1);
++#endif
++ for (i = 0; i < 16; i++) {
++ /* FIXME - what to do if get_user() fails? */
++ get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
++ sp_ptr += sizeof(abi_ulong);
++ }
++ env->wim = new_wim;
++}
++
++void bsd_sparc_flush_windows(CPUSPARCState *env)
++{
++ int offset, cwp1;
++
++ offset = 1;
++ for (;;) {
++ /* if restore would invoke restore_window(), then we can stop */
++ cwp1 = cpu_cwp_inc(env, env->cwp + offset);
++ if (env->wim & (1 << cwp1)) {
++ break;
++ }
++ save_window_offset(env, cwp1);
++ offset++;
++ }
++ cwp1 = cpu_cwp_inc(env, env->cwp + 1);
++ /* set wim so that restore will reload the registers */
++ env->wim = 1 << cwp1;
++#if defined(DEBUG_WIN)
++ printf("bsd_sparc_flush_windows: nb=%d\n", offset - 1);
++#endif
++}
++
+diff --git a/bsd-user/sparc/target_arch_cpu.h b/bsd-user/sparc/target_arch_cpu.h
+new file mode 100644
+index 0000000..f61884b
+--- /dev/null
++++ b/bsd-user/sparc/target_arch_cpu.h
+@@ -0,0 +1,158 @@
++/*
++ * sparc cpu init and loop
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _TARGET_ARCH_CPU_H_
++#define _TARGET_ARCH_CPU_H_
++
++#include "target_arch.h"
++
++#define TARGET_DEFAULT_CPU_MODEL "Fujitsu MB86904"
++
++#define TARGET_CPU_RESET(env) cpu_reset(ENV_GET_CPU(env))
++
++static inline void target_cpu_init(CPUSPARCState *env,
++ struct target_pt_regs *regs)
++{
++ int i;
++
++ env->pc = regs->pc;
++ env->npc = regs->npc;
++ env->y = regs->y;
++ for (i = 0; i < 8; i++) {
++ env->gregs[i] = regs->u_regs[i];
++ }
++ for (i = 0; i < 8; i++) {
++ env->regwptr[i] = regs->u_regs[i + 8];
++ }
++}
++
++static inline void target_cpu_loop(CPUSPARCState *env)
++{
++ CPUState *cs = CPU(sparc_env_get_cpu(env));
++ int trapnr, ret, syscall_nr;
++ /* target_siginfo_t info; */
++
++ while (1) {
++ trapnr = cpu_sparc_exec(env);
++
++ switch (trapnr) {
++ case 0x80:
++ syscall_nr = env->gregs[1];
++ if (bsd_type == target_freebsd) {
++ ret = do_freebsd_syscall(env, syscall_nr,
++ env->regwptr[0], env->regwptr[1],
++ env->regwptr[2], env->regwptr[3],
++ env->regwptr[4], env->regwptr[5], 0, 0);
++ } else if (bsd_type == target_netbsd) {
++ ret = do_netbsd_syscall(env, syscall_nr,
++ env->regwptr[0], env->regwptr[1],
++ env->regwptr[2], env->regwptr[3],
++ env->regwptr[4], env->regwptr[5]);
++ } else { /* if (bsd_type == target_openbsd) */
++ ret = do_openbsd_syscall(env, syscall_nr,
++ env->regwptr[0], env->regwptr[1],
++ env->regwptr[2], env->regwptr[3],
++ env->regwptr[4], env->regwptr[5]);
++ }
++ if ((unsigned int)ret >= (unsigned int)(-515)) {
++ ret = -ret;
++ env->psr |= PSR_CARRY;
++ } else {
++ env->psr &= ~PSR_CARRY;
++ }
++ env->regwptr[0] = ret;
++ /* next instruction */
++ env->pc = env->npc;
++ env->npc = env->npc + 4;
++ break;
++ case 0x83: /* flush windows */
++#ifdef TARGET_ABI32
++ case 0x103:
++#endif
++ bsd_sparc_flush_windows(env);
++ /* next instruction */
++ env->pc = env->npc;
++ env->npc = env->npc + 4;
++ break;
++
++ case TT_WIN_OVF: /* window overflow */
++ bsd_sparc_save_window(env);
++ break;
++
++ case TT_WIN_UNF: /* window underflow */
++ bsd_sparc_restore_window(env);
++ break;
++
++ case TT_TFAULT:
++ case TT_DFAULT:
++#if 0
++ {
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ /* XXX: check env->error_code */
++ info.si_code = TARGET_SEGV_MAPERR;
++ info._sifields._sigfault._addr = env->mmuregs[4];
++ queue_signal(env, info.si_signo, &info);
++ }
++#endif
++ break;
++
++ case EXCP_INTERRUPT:
++ /* just indicate that signals should be handled asap */
++ break;
++
++ case EXCP_DEBUG:
++#if 0
++ {
++ int sig;
++
++ sig = gdb_handlesig(cs, 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); */
++ }
++ }
++#endif
++ break;
++ default:
++ printf("Unhandled trap: 0x%x\n", trapnr);
++ cpu_dump_state(cs, stderr, fprintf, 0);
++ exit(1);
++ }
++ process_pending_signals(env);
++ }
++}
++
++static inline void target_cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
++{
++ if (newsp)
++ env->regwptr[22] = newsp;
++ env->regwptr[0] = 0;
++ /* FIXME: Do we also need to clear CF? */
++ /* XXXXX */
++ printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
++}
++
++static inline void target_cpu_reset(CPUArchState *cpu)
++{
++ cpu_reset(ENV_GET_CPU(cpu));
++}
++
++#endif /* ! _TARGET_ARCH_CPU_H_ */
+diff --git a/bsd-user/sparc/target_arch_elf.h b/bsd-user/sparc/target_arch_elf.h
+new file mode 100644
+index 0000000..b93e2ed
+--- /dev/null
++++ b/bsd-user/sparc/target_arch_elf.h
+@@ -0,0 +1,30 @@
++/*
++ * sparc ELF definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_ELF_H_
++#define _TARGET_ARCH_ELF_H_
++
++#define ELF_START_MMAP 0x80000000
++
++#define elf_check_arch(x) ( (x) == EM_SPARC )
++
++#define ELF_CLASS ELFCLASS32
++#define ELF_DATA ELFDATA2MSB
++#define ELF_ARCH EM_SPARC
++
++#endif /* _TARGET_ARCH_ELF_H_ */
+diff --git a/bsd-user/sparc/target_arch_signal.h b/bsd-user/sparc/target_arch_signal.h
+new file mode 100644
+index 0000000..f934f8c
+--- /dev/null
++++ b/bsd-user/sparc/target_arch_signal.h
+@@ -0,0 +1,77 @@
++#ifndef TARGET_ARCH_SIGNAL_H
++#define TARGET_ARCH_SIGNAL_H
++
++#include "cpu.h"
++
++/* Size of the signal trampolin code placed on the stack. */
++/* #define TARGET_SZSIGCODE (0) */ /* XXX to be added. */
++
++/* compare to sparc64/include/_limits.h */
++#define TARGET_MINSIGSTKSZ (1024 * 4) /* min sig stack size */
++#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
++
++#define TARGET_MC_GET_CLEAR_RET 0x0001
++
++struct target_sigcontext {
++ /* to be added */
++};
++
++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 {
++ 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];
++};
++
++/*
++ * Compare to sparc64/sparc64/machdep.c sendsig()
++ * Assumes that target stack frame memory is locked.
++ */
++static inline abi_long set_sigtramp_args(CPUSPARCState *regs,
++ int sig, struct target_sigframe *frame, abi_ulong frame_addr,
++ struct target_sigaction *ka)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++/* Compare to sparc64/sparc64/machdep.c get_mcontext() */
++static inline abi_long get_mcontext(CPUSPARCState *regs,
++ target_mcontext_t *mcp, int flags)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++/* Compare to sparc64/space64/machdep.c set_mcontext() */
++static inline abi_long set_mcontext(CPUSPARCState *regs,
++ target_mcontext_t *mcp, int srflag)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++static inline abi_long get_ucontext_sigreturn(CPUSPARCState *regs,
++ abi_ulong target_sf, abi_ulong *target_uc)
++{
++ /* XXX */
++ *target_uc = 0;
++ return -TARGET_EOPNOTSUPP;
++}
++
++#endif /* TARGET_ARCH_SIGNAL_H */
+diff --git a/bsd-user/sparc/target_arch_sigtramp.h b/bsd-user/sparc/target_arch_sigtramp.h
+new file mode 100644
+index 0000000..f0f36d1
+--- /dev/null
++++ b/bsd-user/sparc/target_arch_sigtramp.h
+@@ -0,0 +1,11 @@
++
++#ifndef _TARGET_ARCH_SIGTRAMP_H_
++#define _TARGET_ARCH_SIGTRAMP_H_
++
++static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
++ unsigned sys_sigreturn)
++{
++
++ return -TARGET_EOPNOTSUPP;
++}
++#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
+diff --git a/bsd-user/sparc/target_arch_sysarch.h b/bsd-user/sparc/target_arch_sysarch.h
+new file mode 100644
+index 0000000..454c084
+--- /dev/null
++++ b/bsd-user/sparc/target_arch_sysarch.h
+@@ -0,0 +1,52 @@
++/*
++ * SPARC sysarch() system call emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __ARCH_SYSARCH_H_
++#define __ARCH_SYSARCH_H_
++
++#include "syscall.h"
++
++static inline abi_long do_freebsd_arch_sysarch(void *env, int op,
++ abi_ulong parms)
++{
++ int ret = 0;
++
++ switch (op) {
++ case TARGET_SPARC_SIGTRAMP_INSTALL:
++ /* XXX not currently handled */
++ case TARGET_SPARC_UTRAP_INSTALL:
++ /* XXX not currently handled */
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++
++ return ret;
++}
++
++static inline void do_freebsd_arch_print_sysarch(
++ const struct syscallname *name, abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
++{
++
++ gemu_log("%s(%d, " TARGET_ABI_FMT_lx ", " TARGET_ABI_FMT_lx ", "
++ TARGET_ABI_FMT_lx ")", name->name, (int)arg1, arg2, arg3, arg4);
++}
++
++#endif /*!__ARCH_SYSARCH_H_ */
+diff --git a/bsd-user/sparc/target_arch_thread.h b/bsd-user/sparc/target_arch_thread.h
+new file mode 100644
+index 0000000..fe607be
+--- /dev/null
++++ b/bsd-user/sparc/target_arch_thread.h
+@@ -0,0 +1,39 @@
++/*
++ * sparc thread support
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_THREAD_H_
++#define _TARGET_ARCH_THREAD_H_
++
++/* Compare to vm_machdep.c cpu_set_upcall_kse() */
++static inline void target_thread_set_upcall(CPUSPARCState *regs,
++ abi_ulong entry, abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
++{
++ /* XXX */
++}
++
++static inline void target_thread_init(struct target_pt_regs *regs,
++ struct image_info *infop)
++{
++ regs->psr = 0;
++ regs->pc = infop->entry;
++ regs->npc = regs->pc + 4;
++ regs->y = 0;
++ regs->u_regs[14] = infop->start_stack - 16 * 4;
++}
++
++#endif /* !_TARGET_ARCH_THREAD_H_ */
+diff --git a/bsd-user/sparc/target_arch_vmparam.h b/bsd-user/sparc/target_arch_vmparam.h
+new file mode 100644
+index 0000000..5f28fcf
+--- /dev/null
++++ b/bsd-user/sparc/target_arch_vmparam.h
+@@ -0,0 +1,37 @@
++#ifndef _TARGET_ARCH_VMPARAM_H_
++#define _TARGET_ARCH_VMPARAM_H_
++
++#include "cpu.h"
++
++#define TARGET_MAXTSIZ (1*1024*1024*1024) /* max text size */
++#define TARGET_DFLDSIZ (128*1024*1024) /* initial data size limit */
++#define TARGET_MAXDSIZ (1*1024*1024*1024) /* max data size */
++#define TARGET_DFLSSIZ (128*1024*1024) /* initial stack size limit */
++#define TARGET_MAXSSIZ (1*1024*1024*1024) /* max stack size */
++#define TARGET_SGROWSIZ (128*1024) /* amount to grow stack */
++
++#define TARGET_RESERVED_VA 0xf7000000
++
++/* XXX this may not be right */
++#define TARGET_VM_MAXUSER_ADDRESS (0xc0000000 - (512 * 1024 * 1024))
++#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
++
++#ifndef UREG_I6
++#define UREG_I6 6
++#endif
++#ifndef UREG_FP
++#define UREG_FP UREG_I6
++#endif
++
++static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
++{
++ return state->regwptr[UREG_FP];
++}
++
++static inline void set_second_rval(CPUSPARCState *state, abi_ulong retval2)
++{
++ state->regwptr[1] = retval2;
++}
++
++#endif /* !_TARGET_ARCH_VMPARAM_H_ */
++
+diff --git a/bsd-user/sparc/target_signal.h b/bsd-user/sparc/target_signal.h
+index 5b2abba..181867a 100644
+--- a/bsd-user/sparc/target_signal.h
++++ b/bsd-user/sparc/target_signal.h
+@@ -19,9 +19,4 @@ typedef struct target_sigaltstack {
+ #define UREG_FP UREG_I6
+ #endif
+
+-static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+-{
+- return state->regwptr[UREG_FP];
+-}
+-
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/sparc64/syscall.h b/bsd-user/sparc64/syscall.h
+index 81a816d..58cc38d 100644
+--- a/bsd-user/sparc64/syscall.h
++++ b/bsd-user/sparc64/syscall.h
+@@ -1,3 +1,22 @@
++/*
++ * sparc64 dependent system call definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _SPARC64_SYSCALL_H_
++#define _SPARC64_SYSCALL_H_
+ struct target_pt_regs {
+ abi_ulong u_regs[16];
+ abi_ulong tstate;
+@@ -7,4 +26,11 @@ struct target_pt_regs {
+ abi_ulong fprs;
+ };
+
+-#define UNAME_MACHINE "sun4u"
++#define UNAME_MACHINE "sun4u"
++#define TARGET_HW_MACHINE "sparc"
++#define TARGET_HW_MACHINE_ARCH "sparc64"
++
++#define TARGET_SPARC_UTRAP_INSTALL 1
++#define TARGET_SPARC_SIGTRAMP_INSTALL 2
++
++#endif /* !_SPARC64_SYSCALL_H_ */
+diff --git a/bsd-user/sparc64/target_arch.h b/bsd-user/sparc64/target_arch.h
+new file mode 100644
+index 0000000..46bbcf8
+--- /dev/null
++++ b/bsd-user/sparc64/target_arch.h
+@@ -0,0 +1,11 @@
++
++#ifndef _TARGET_ARCH_H_
++#define _TARGET_ARCH_H_
++
++void bsd_sparc64_save_window(CPUSPARCState *env);
++void bsd_sparc64_restore_window(CPUSPARCState *env);
++void bsd_sparc64_flush_windows(CPUSPARCState *env);
++
++#define target_cpu_set_tls(env, newtls)
++
++#endif /* ! _TARGET_ARCH_H_ */
+diff --git a/bsd-user/sparc64/target_arch_cpu.c b/bsd-user/sparc64/target_arch_cpu.c
+new file mode 100644
+index 0000000..e7bede8
+--- /dev/null
++++ b/bsd-user/sparc64/target_arch_cpu.c
+@@ -0,0 +1,118 @@
++/*
++ * sparc64 cpu related code
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++
++#include "cpu.h"
++#include "qemu.h"
++
++#include "target_arch.h"
++
++#define SPARC64_STACK_BIAS 2047
++
++/* #define DEBUG_WIN */
++/* WARNING: dealing with register windows _is_ complicated. More info
++ can be found at http://www.sics.se/~psm/sparcstack.html */
++static int get_reg_index(CPUSPARCState *env, int cwp, int index)
++{
++ index = (index + cwp * 16) % (16 * env->nwindows);
++ /* wrap handling : if cwp is on the last window, then we use the
++ registers 'after' the end */
++ if (index < 8 && env->cwp == env->nwindows - 1) {
++ index += 16 * env->nwindows;
++ }
++ return index;
++}
++
++/* save the register window 'cwp1' */
++static void save_window_offset(CPUSPARCState *env, int cwp1)
++{
++ unsigned int i;
++ abi_ulong sp_ptr;
++
++ sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
++ if (sp_ptr & 3) {
++ sp_ptr += SPARC64_STACK_BIAS;
++ }
++#if defined(DEBUG_WIN)
++ printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n",
++ sp_ptr, cwp1);
++#endif
++ for (i = 0; i < 16; i++) {
++ /* FIXME - what to do if put_user() fails? */
++ put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
++ sp_ptr += sizeof(abi_ulong);
++ }
++}
++
++void bsd_sparc64_save_window(CPUSPARCState *env)
++{
++ save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
++ env->cansave++;
++ env->canrestore--;
++}
++
++void bsd_sparc64_restore_window(CPUSPARCState *env)
++{
++ unsigned int i, cwp1;
++ abi_ulong sp_ptr;
++
++ /* restore the invalid window */
++ cwp1 = cpu_cwp_inc(env, env->cwp + 1);
++ sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)];
++ if (sp_ptr & 3) {
++ sp_ptr += SPARC64_STACK_BIAS;
++ }
++#if defined(DEBUG_WIN)
++ printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n",
++ sp_ptr, cwp1);
++#endif
++ for (i = 0; i < 16; i++) {
++ /* FIXME - what to do if get_user() fails? */
++ get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr);
++ sp_ptr += sizeof(abi_ulong);
++ }
++ env->canrestore++;
++ if (env->cleanwin < env->nwindows - 1) {
++ env->cleanwin++;
++ }
++ env->cansave--;
++}
++
++void bsd_sparc64_flush_windows(CPUSPARCState *env)
++{
++ int offset, cwp1;
++
++ offset = 1;
++ for (;;) {
++ /* if restore would invoke restore_window(), then we can stop */
++ cwp1 = cpu_cwp_inc(env, env->cwp + offset);
++ if (env->canrestore == 0) {
++ break;
++ }
++ env->cansave++;
++ env->canrestore--;
++ save_window_offset(env, cwp1);
++ offset++;
++ }
++ cwp1 = cpu_cwp_inc(env, env->cwp + 1);
++#if defined(DEBUG_WIN)
++ printf("bsd_sparc64_flush_windows: nb=%d\n", offset - 1);
++#endif
++}
++
+diff --git a/bsd-user/sparc64/target_arch_cpu.h b/bsd-user/sparc64/target_arch_cpu.h
+new file mode 100644
+index 0000000..e497711
+--- /dev/null
++++ b/bsd-user/sparc64/target_arch_cpu.h
+@@ -0,0 +1,191 @@
++/*
++ * sparc64 cpu init and loop
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _TARGET_ARCH_CPU_H_
++#define _TARGET_ARCH_CPU_H_
++
++#include "target_arch.h"
++
++#define TARGET_DEFAULT_CPU_MODEL "TI UltraSparc II"
++
++#define TARGET_CPU_RESET(env) cpu_reset(ENV_GET_CPU(env))
++
++static inline void target_cpu_init(CPUSPARCState *env,
++ struct target_pt_regs *regs)
++{
++ int i;
++
++ env->pc = regs->pc;
++ env->npc = regs->npc;
++ env->y = regs->y;
++ for (i = 0; i < 8; i++) {
++ env->gregs[i] = regs->u_regs[i];
++ }
++ for (i = 0; i < 8; i++) {
++ env->regwptr[i] = regs->u_regs[i + 8];
++ }
++}
++
++
++static inline void target_cpu_loop(CPUSPARCState *env)
++{
++ CPUState *cs = CPU(sparc_env_get_cpu(env));
++ int trapnr, ret, syscall_nr;
++ /* target_siginfo_t info; */
++
++ while (1) {
++ trapnr = cpu_sparc_exec(env);
++
++ switch (trapnr) {
++ /* FreeBSD uses 0x141 for syscalls too */
++ case 0x141:
++ if (bsd_type != target_freebsd) {
++ goto badtrap;
++ }
++ case 0x100:
++ syscall_nr = env->gregs[1];
++ if (bsd_type == target_freebsd) {
++ ret = do_freebsd_syscall(env, syscall_nr,
++ env->regwptr[0], env->regwptr[1],
++ env->regwptr[2], env->regwptr[3],
++ env->regwptr[4], env->regwptr[5], 0, 0);
++ } else if (bsd_type == target_netbsd) {
++ ret = do_netbsd_syscall(env, syscall_nr,
++ env->regwptr[0], env->regwptr[1],
++ env->regwptr[2], env->regwptr[3],
++ env->regwptr[4], env->regwptr[5]);
++ } else { /* if (bsd_type == target_openbsd) */
++ syscall_nr &= ~(TARGET_OPENBSD_SYSCALL_G7RFLAG |
++ TARGET_OPENBSD_SYSCALL_G2RFLAG);
++ ret = do_openbsd_syscall(env, syscall_nr,
++ env->regwptr[0], env->regwptr[1],
++ env->regwptr[2], env->regwptr[3],
++ env->regwptr[4], env->regwptr[5]);
++ }
++ if ((unsigned int)ret >= (unsigned int)(-515)) {
++ ret = -ret;
++#if !defined(TARGET_ABI32)
++ env->xcc |= PSR_CARRY;
++#else
++ env->psr |= PSR_CARRY;
++#endif
++ } else {
++#if !defined(TARGET_ABI32)
++ env->xcc &= ~PSR_CARRY;
++#else
++ env->psr &= ~PSR_CARRY;
++#endif
++ }
++ env->regwptr[0] = ret;
++ /* next instruction */
++ if (bsd_type == target_openbsd &&
++ env->gregs[1] & TARGET_OPENBSD_SYSCALL_G2RFLAG) {
++ env->pc = env->gregs[2];
++ env->npc = env->pc + 4;
++ } else if (bsd_type == target_openbsd &&
++ env->gregs[1] & TARGET_OPENBSD_SYSCALL_G7RFLAG) {
++ env->pc = env->gregs[7];
++ env->npc = env->pc + 4;
++ } else {
++ env->pc = env->npc;
++ env->npc = env->npc + 4;
++ }
++ break;
++
++ case 0x83: /* flush windows */
++#ifdef TARGET_ABI32
++ case 0x103:
++#endif
++ bsd_sparc64_flush_windows(env);
++ /* next instruction */
++ env->pc = env->npc;
++ env->npc = env->npc + 4;
++ break;
++
++ case TT_SPILL: /* window overflow */
++ bsd_sparc64_save_window(env);
++ break;
++
++ case TT_FILL: /* window underflow */
++ bsd_sparc64_restore_window(env);
++ break;
++
++ case TT_TFAULT:
++ case TT_DFAULT:
++#if 0
++ {
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ /* XXX: check env->error_code */
++ info.si_code = TARGET_SEGV_MAPERR;
++ if (trapnr == TT_DFAULT) {
++ info._sifields._sigfault._addr = env->dmmuregs[4];
++ } else {
++ info._sifields._sigfault._addr = env->tsptr->tpc;
++ /* queue_signal(env, info.si_signo, &info); */
++ }
++ }
++#endif
++ break;
++
++ case EXCP_INTERRUPT:
++ /* just indicate that signals should be handled asap */
++ break;
++
++ case EXCP_DEBUG:
++ {
++ int sig;
++
++ sig = gdb_handlesig(cs, TARGET_SIGTRAP);
++#if 0
++ if (sig) {
++ info.si_signo = sig;
++ info.si_errno = 0;
++ info.si_code = TARGET_TRAP_BRKPT;
++ /* queue_signal(env, info.si_signo, &info); */
++ }
++#endif
++ }
++ break;
++
++ default:
++badtrap:
++ printf("Unhandled trap: 0x%x\n", trapnr);
++ cpu_dump_state(cs, stderr, fprintf, 0);
++ exit(1);
++ }
++ process_pending_signals(env);
++ }
++}
++
++static inline void target_cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
++{
++ if (newsp)
++ env->regwptr[22] = newsp;
++ env->regwptr[0] = 0;
++ /* FIXME: Do we also need to clear CF? */
++ /* XXXXX */
++ printf ("HELPME: %s:%d\n", __FILE__, __LINE__);
++}
++
++static inline void target_cpu_reset(CPUArchState *cpu)
++{
++ cpu_reset(ENV_GET_CPU(cpu));
++}
++
++#endif /* ! _TARGET_ARCH_CPU_H_ */
+diff --git a/bsd-user/sparc64/target_arch_elf.h b/bsd-user/sparc64/target_arch_elf.h
+new file mode 100644
+index 0000000..f2b8e12
+--- /dev/null
++++ b/bsd-user/sparc64/target_arch_elf.h
+@@ -0,0 +1,34 @@
++/*
++ * sparc64 ELF definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_ELF_H_
++#define _TARGET_ARCH_ELF_H_
++
++#define ELF_START_MMAP 0x80000000
++
++#ifndef TARGET_ABI32
++#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
++#else
++#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
++#endif
++
++#define ELF_CLASS ELFCLASS64
++#define ELF_DATA ELFDATA2MSB
++#define ELF_ARCH EM_SPARCV9
++
++#endif /* _TARGET_ARCH_ELF_H_ */
+diff --git a/bsd-user/sparc64/target_arch_signal.h b/bsd-user/sparc64/target_arch_signal.h
+new file mode 100644
+index 0000000..1529b0f
+--- /dev/null
++++ b/bsd-user/sparc64/target_arch_signal.h
+@@ -0,0 +1,94 @@
++/*
++ * sparc64 dependent signal definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_SIGNAL_H_
++#define _TARGET_ARCH_SIGNAL_H_
++
++#include "cpu.h"
++
++/* Size of the signal trampolin code placed on the stack. */
++/* #define TARGET_SZSIGCODE (0) */ /* XXX to be added. */
++
++/* compare to sparc64/include/_limits.h */
++#define TARGET_MINSIGSTKSZ (1024 * 4) /* min sig stack size */
++#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
++
++#define TARGET_MC_GET_CLEAR_RET 0x0001
++
++struct target_sigcontext {
++ /* to be added */
++};
++
++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 {
++ 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];
++};
++
++/*
++ * Compare to sparc64/sparc64/machdep.c sendsig()
++ * Assumes that target stack frame memory is locked.
++ */
++static inline abi_long set_sigtramp_args(CPUSPARCState *regs,
++ int sig, struct target_sigframe *frame, abi_ulong frame_addr,
++ struct target_sigaction *ka)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++/* Compare to sparc64/sparc64/machdep.c get_mcontext() */
++static inline abi_long get_mcontext(CPUSPARCState *regs,
++ target_mcontext_t *mcp, int flags)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++/* Compare to sparc64/space64/machdep.c set_mcontext() */
++static inline abi_long set_mcontext(CPUSPARCState *regs,
++ target_mcontext_t *mcp, int srflag)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++static inline abi_long get_ucontext_sigreturn(CPUSPARCState *regs,
++ abi_ulong target_sf, abi_ulong *target_uc)
++{
++ /* XXX */
++ *target_uc = 0;
++ return -TARGET_EOPNOTSUPP;
++}
++
++#endif /* !_TARGET_ARCH_SIGNAL_H_ */
+diff --git a/bsd-user/sparc64/target_arch_sigtramp.h b/bsd-user/sparc64/target_arch_sigtramp.h
+new file mode 100644
+index 0000000..f0f36d1
+--- /dev/null
++++ b/bsd-user/sparc64/target_arch_sigtramp.h
+@@ -0,0 +1,11 @@
++
++#ifndef _TARGET_ARCH_SIGTRAMP_H_
++#define _TARGET_ARCH_SIGTRAMP_H_
++
++static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
++ unsigned sys_sigreturn)
++{
++
++ return -TARGET_EOPNOTSUPP;
++}
++#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
+diff --git a/bsd-user/sparc64/target_arch_sysarch.h b/bsd-user/sparc64/target_arch_sysarch.h
+new file mode 100644
+index 0000000..84e1339
+--- /dev/null
++++ b/bsd-user/sparc64/target_arch_sysarch.h
+@@ -0,0 +1,52 @@
++/*
++ * SPARC64 sysarch() system call emulation
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __ARCH_SYSARCH_H_
++#define __ARCH_SYSARCH_H_
++
++#include "syscall.h"
++
++static inline abi_long do_freebsd_arch_sysarch(void *env, int op,
++ abi_ulong parms)
++{
++ int ret = 0;
++
++ switch (op) {
++ case TARGET_SPARC_SIGTRAMP_INSTALL:
++ /* XXX not currently handled */
++ case TARGET_SPARC_UTRAP_INSTALL:
++ /* XXX not currently handled */
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++
++ return ret;
++}
++
++static inline void do_freebsd_arch_print_sysarch(
++ const struct syscallname *name, abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
++{
++
++ gemu_log("%s(%d, " TARGET_ABI_FMT_lx ", " TARGET_ABI_FMT_lx ", "
++ TARGET_ABI_FMT_lx ")", name->name, (int)arg1, arg2, arg3, arg4);
++}
++
++#endif /*!__ARCH_SYSARCH_H_ */
+diff --git a/bsd-user/sparc64/target_arch_thread.h b/bsd-user/sparc64/target_arch_thread.h
+new file mode 100644
+index 0000000..2e5585a
+--- /dev/null
++++ b/bsd-user/sparc64/target_arch_thread.h
+@@ -0,0 +1,55 @@
++/*
++ * sparc64 thread support
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_THREAD_H_
++#define _TARGET_ARCH_THREAD_H_
++
++#define STACK_BIAS 2047
++
++/* Compare to vm_machdep.c cpu_set_upcall_kse() */
++static inline void target_thread_set_upcall(CPUSPARCState *regs,
++ abi_ulong entry, abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
++{
++ /* XXX */
++}
++
++static inline void target_thread_init(struct target_pt_regs *regs,
++ struct image_info *infop)
++{
++#ifndef TARGET_ABI32
++ regs->tstate = 0;
++#endif
++ regs->pc = infop->entry;
++ regs->npc = regs->pc + 4;
++ regs->y = 0;
++#ifdef TARGET_ABI32
++ regs->u_regs[14] = infop->start_stack - 16 * 4;
++#else
++ if (personality(infop->personality) == PER_LINUX32)
++ regs->u_regs[14] = infop->start_stack - 16 * 4;
++ else {
++ regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
++ if (bsd_type == target_freebsd) {
++ regs->u_regs[8] = infop->start_stack;
++ regs->u_regs[11] = infop->start_stack;
++ }
++ }
++#endif
++}
++
++#endif /* !_TARGET_ARCH_THREAD_H_ */
+diff --git a/bsd-user/sparc64/target_arch_vmparam.h b/bsd-user/sparc64/target_arch_vmparam.h
+new file mode 100644
+index 0000000..2c2323b
+--- /dev/null
++++ b/bsd-user/sparc64/target_arch_vmparam.h
+@@ -0,0 +1,37 @@
++#ifndef _TARGET_ARCH_VMPARAM_H_
++#define _TARGET_ARCH_VMPARAM_H_
++
++#include "cpu.h"
++
++/* compare to amd64/include/vmparam.h */
++#define TARGET_MAXTSIZ (1*1024*1024*1024) /* max text size */
++#define TARGET_DFLDSIZ (128*1024*1024) /* initial data size limit */
++#define TARGET_MAXDSIZ (1*1024*1024*1024) /* max data size */
++#define TARGET_DFLSSIZ (128*1024*1024) /* initial stack size limit */
++#define TARGET_MAXSSIZ (1*1024*1024*1024) /* max stack size */
++#define TARGET_SGROWSIZ (128*1024) /* amount to grow stack */
++
++/* XXX */
++#define TARGET_VM_MINUSER_ADDRESS (0x0000000000000000UL)
++#define TARGET_VM_MAXUSER_ADDRESS (0x000007fe00000000UL)
++#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
++
++#ifndef UREG_I6
++#define UREG_I6 6
++#endif
++#ifndef UREG_FP
++#define UREG_FP UREG_I6
++#endif
++
++static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
++{
++ return state->regwptr[UREG_FP];
++}
++
++static inline void set_second_rval(CPUSPARCState *state, abi_ulong retval2)
++{
++ state->regwptr[1] = retval2;
++}
++
++#endif /* !_TARGET_ARCH_VMPARAM_H_ */
++
+diff --git a/bsd-user/sparc64/target_signal.h b/bsd-user/sparc64/target_signal.h
+index 5b2abba..181867a 100644
+--- a/bsd-user/sparc64/target_signal.h
++++ b/bsd-user/sparc64/target_signal.h
+@@ -19,9 +19,4 @@ typedef struct target_sigaltstack {
+ #define UREG_FP UREG_I6
+ #endif
+
+-static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+-{
+- return state->regwptr[UREG_FP];
+-}
+-
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/strace.c b/bsd-user/strace.c
+index d73bbca..60aabc3 100644
+--- a/bsd-user/strace.c
++++ b/bsd-user/strace.c
+@@ -1,37 +1,73 @@
++/*
++ * System call tracing and debugging
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
+ #include <stdio.h>
+ #include <errno.h>
+ #include <sys/select.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ #include <sys/syscall.h>
++#include <sys/ioccom.h>
++#include <ctype.h>
++
+ #include "qemu.h"
+
+-int do_strace=0;
++#include "os-strace.h" /* OS dependent strace print functions */
+
+-struct syscallname {
+- int nr;
+- const char *name;
+- const char *format;
+- void (*call)(const struct syscallname *,
+- abi_long, abi_long, abi_long,
+- abi_long, abi_long, abi_long);
+- void (*result)(const struct syscallname *, abi_long);
+-};
++int do_strace;
+
+ /*
+ * Utility functions
+ */
+
+-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)
++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)
+ {
+ abi_ulong arg_ptr_addr;
+ char *s;
+
+- if (!(s = lock_user_string(arg1)))
++ s = lock_user_string(arg1);
++ if (s == NULL) {
+ return;
++ }
+ gemu_log("%s(\"%s\",{", name->name, s);
+ unlock_user(s, arg1, 0);
+
+@@ -39,29 +75,56 @@ print_execve(const struct syscallname *name,
+ abi_ulong *arg_ptr, arg_addr;
+
+ arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
+- if (!arg_ptr)
++ if (!arg_ptr) {
+ return;
++ }
+ arg_addr = tswapl(*arg_ptr);
+ unlock_user(arg_ptr, arg_ptr_addr, 0);
+- if (!arg_addr)
++ if (!arg_addr) {
+ break;
++ }
+ if ((s = lock_user_string(arg_addr))) {
+ gemu_log("\"%s\",", s);
+ unlock_user(s, arg_addr, 0);
+ }
+ }
+-
+ 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)
++{
++ /* This is os dependent. */
++ do_os_print_sysarch(name, arg1, arg2, arg3, arg4, arg5, arg6);
++}
++
+ /*
+ * Variants for the return value output function
+ */
+
+-static void
+-print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
++static void print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
+ {
+-if( ret == -1 ) {
++ if (ret == -1) {
+ gemu_log(" = -1 errno=%d (%s)\n", errno, strerror(errno));
+ } else {
+ gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
+@@ -90,10 +153,9 @@ static const struct syscallname openbsd_scnames[] = {
+ #include "openbsd/strace.list"
+ };
+
+-static void
+-print_syscall(int num, const struct syscallname *scnames, unsigned int nscnames,
+- abi_long arg1, abi_long arg2, abi_long arg3,
+- abi_long arg4, abi_long arg5, abi_long arg6)
++static void print_syscall(int num, const struct syscallname *scnames,
++ unsigned int nscnames, abi_long arg1, abi_long arg2, abi_long arg3,
++ abi_long arg4, abi_long arg5, abi_long arg6)
+ {
+ unsigned int i;
+ const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ","
+@@ -102,36 +164,37 @@ print_syscall(int num, const struct syscallname *scnames, unsigned int nscnames,
+
+ gemu_log("%d ", getpid() );
+
+- for (i = 0; i < nscnames; i++)
++ for (i = 0; i < nscnames; i++) {
+ if (scnames[i].nr == num) {
+ if (scnames[i].call != NULL) {
+ scnames[i].call(&scnames[i], arg1, arg2, arg3, arg4, arg5,
+- arg6);
++ arg6);
+ } else {
+ /* XXX: this format system is broken because it uses
+ host types and host pointers for strings */
+- if (scnames[i].format != NULL)
++ if (scnames[i].format != NULL) {
+ format = scnames[i].format;
+- gemu_log(format, scnames[i].name, arg1, arg2, arg3, arg4,
+- arg5, arg6);
++ }
++ gemu_log(format, scnames[i].name, arg1, arg2, arg3, arg4, arg5,
++ arg6);
+ }
+ return;
+ }
++ }
+ gemu_log("Unknown syscall %d\n", num);
+ }
+
+-static void
+-print_syscall_ret(int num, abi_long ret, const struct syscallname *scnames,
+- unsigned int nscnames)
++static void print_syscall_ret(int num, abi_long ret,
++ const struct syscallname *scnames, unsigned int nscnames)
+ {
+ unsigned int i;
+
+- for (i = 0; i < nscnames; i++)
++ for (i = 0; i < nscnames; i++) {
+ if (scnames[i].nr == num) {
+ if (scnames[i].result != NULL) {
+ scnames[i].result(&scnames[i], ret);
+ } else {
+- if( ret < 0 ) {
++ if (ret < 0) {
+ gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret,
+ strerror(-ret));
+ } else {
+@@ -140,52 +203,50 @@ print_syscall_ret(int num, abi_long ret, const struct syscallname *scnames,
+ }
+ break;
+ }
++ }
+ }
+
+ /*
+ * The public interface to this module.
+ */
+-void
+-print_freebsd_syscall(int num,
+- abi_long arg1, abi_long arg2, abi_long arg3,
+- abi_long arg4, abi_long arg5, abi_long arg6)
++void print_freebsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
++ abi_long arg4, abi_long arg5, abi_long arg6)
+ {
+- print_syscall(num, freebsd_scnames, ARRAY_SIZE(freebsd_scnames),
+- arg1, arg2, arg3, arg4, arg5, arg6);
++
++ print_syscall(num, freebsd_scnames, ARRAY_SIZE(freebsd_scnames), arg1, arg2,
++ arg3, arg4, arg5, arg6);
+ }
+
+-void
+-print_freebsd_syscall_ret(int num, abi_long ret)
++void print_freebsd_syscall_ret(int num, abi_long ret)
+ {
++
+ print_syscall_ret(num, ret, freebsd_scnames, ARRAY_SIZE(freebsd_scnames));
+ }
+
+-void
+-print_netbsd_syscall(int num,
+- abi_long arg1, abi_long arg2, abi_long arg3,
+- abi_long arg4, abi_long arg5, abi_long arg6)
++void print_netbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
++ abi_long arg4, abi_long arg5, abi_long arg6)
+ {
++
+ print_syscall(num, netbsd_scnames, ARRAY_SIZE(netbsd_scnames),
+ arg1, arg2, arg3, arg4, arg5, arg6);
+ }
+
+-void
+-print_netbsd_syscall_ret(int num, abi_long ret)
++void print_netbsd_syscall_ret(int num, abi_long ret)
+ {
++
+ print_syscall_ret(num, ret, netbsd_scnames, ARRAY_SIZE(netbsd_scnames));
+ }
+
+-void
+-print_openbsd_syscall(int num,
+- abi_long arg1, abi_long arg2, abi_long arg3,
+- abi_long arg4, abi_long arg5, abi_long arg6)
++void print_openbsd_syscall(int num, abi_long arg1, abi_long arg2, abi_long arg3,
++ abi_long arg4, abi_long arg5, abi_long arg6)
+ {
+- print_syscall(num, openbsd_scnames, ARRAY_SIZE(openbsd_scnames),
+- arg1, arg2, arg3, arg4, arg5, arg6);
++
++ print_syscall(num, openbsd_scnames, ARRAY_SIZE(openbsd_scnames), arg1, arg2,
++ arg3, arg4, arg5, arg6);
+ }
+
+-void
+-print_openbsd_syscall_ret(int num, abi_long ret)
++void print_openbsd_syscall_ret(int num, abi_long ret)
+ {
++
+ print_syscall_ret(num, ret, openbsd_scnames, ARRAY_SIZE(openbsd_scnames));
+ }
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index a4d1583..35bf394 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) 2013 Stacey D. 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
+@@ -16,403 +17,1538 @@
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+-#include <stdlib.h>
+ #include <stdio.h>
+ #include <stdint.h>
+ #include <stdarg.h>
+ #include <string.h>
+ #include <errno.h>
+-#include <unistd.h>
+-#include <fcntl.h>
+ #include <time.h>
+-#include <limits.h>
+ #include <sys/types.h>
+-#include <sys/mman.h>
+ #include <sys/syscall.h>
+ #include <sys/param.h>
+ #include <sys/sysctl.h>
+-#include <utime.h>
+
+ #include "qemu.h"
+ #include "qemu-common.h"
+
+-//#define DEBUG
++#define target_to_host_bitmask(x, tbl) (x)
++
++/* BSD independent syscall shims */
++#include "bsd-file.h"
++#include "bsd-ioctl.h"
++#include "bsd-mem.h"
++#include "bsd-misc.h"
++#include "bsd-proc.h"
++#include "bsd-signal.h"
++#include "bsd-socket.h"
++
++/* *BSD dependent syscall shims */
++#include "os-extattr.h"
++#include "os-time.h"
++#include "os-misc.h"
++#include "os-proc.h"
++#include "os-signal.h"
++#include "os-socket.h"
++#include "os-stat.h"
++#include "os-thread.h"
++
++/* #define DEBUG */
++
++/*
++ * errno conversion.
++ */
++abi_long get_errno(abi_long ret)
++{
++
++ if (ret == -1) {
++ /* XXX need to translate host -> target errnos here */
++ return -(errno);
++ } else {
++ return ret;
++ }
++}
++
++int host_to_target_errno(int err)
++{
++ /* XXX need to translate host errnos here */
++ return err;
++}
++
++int is_error(abi_long ret)
++{
++
++ return (abi_ulong)ret >= (abi_ulong)(-4096);
++}
++
++/* FIXME
++ * lock_iovec()/unlock_iovec() have a return code of 0 for success where
++ * other lock functions have a return code of 0 for failure.
++ */
++static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
++ int count, int copy)
++{
++ struct target_iovec *target_vec;
++ abi_ulong base;
++ int i;
++
++ target_vec = lock_user(VERIFY_READ, target_addr,
++ count * sizeof(struct target_iovec), 1);
++ if (!target_vec) {
++ return -TARGET_EFAULT;
++ }
++ for (i = 0; i < count; i++) {
++ base = tswapl(target_vec[i].iov_base);
++ vec[i].iov_len = tswapl(target_vec[i].iov_len);
++ if (vec[i].iov_len != 0) {
++ vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
++ /* Don't check lock_user return value. We must call writev even
++ if a element has invalid base address. */
++ } else {
++ /* zero length pointer is ignored */
++ vec[i].iov_base = NULL;
++ }
++ }
++ unlock_user (target_vec, target_addr, 0);
++ return 0;
++}
++
++static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
++ int count, int copy)
++{
++ struct target_iovec *target_vec;
++ abi_ulong base;
++ int i;
++
++ target_vec = lock_user(VERIFY_READ, target_addr,
++ count * sizeof(struct target_iovec), 1);
++ if (!target_vec)
++ return -TARGET_EFAULT;
++ for (i = 0; i < count; i++) {
++ if (target_vec[i].iov_base) {
++ base = tswapl(target_vec[i].iov_base);
++ unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
++ }
++ }
++ unlock_user (target_vec, target_addr, 0);
++
++ return 0;
++}
++
++
++/* stub for arm semihosting support */
++abi_long do_brk(abi_ulong new_brk)
++{
++ return do_obreak(new_brk);
++}
++
++/* 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;
++
++#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) {
++ /*
++ * process system calls
++ */
++ case TARGET_FREEBSD_NR_fork: /* fork(2) */
++ ret = do_freebsd_fork(cpu_env);
++ break;
++
++ case TARGET_FREEBSD_NR_vfork: /* vfork(2) */
++ ret = do_freebsd_vfork(cpu_env);
++ break;
++
++ case TARGET_FREEBSD_NR_rfork: /* rfork(2) */
++ ret = do_freebsd_rfork(cpu_env, arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_pdfork: /* pdfork(2) */
++ ret = do_freebsd_pdfork(cpu_env, arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_execve: /* execve(2) */
++ ret = do_freebsd_execve(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_fexecve: /* fexecve(2) */
++ ret = do_freebsd_fexecve(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_wait4: /* wait4(2) */
++ ret = do_freebsd_wait4(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_exit: /* exit(2) */
++ ret = do_bsd_exit(cpu_env, arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_getgroups: /* getgroups(2) */
++ ret = do_bsd_getgroups(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_setgroups: /* setgroups(2) */
++ ret = do_bsd_setgroups(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_umask: /* umask(2) */
++ ret = do_bsd_umask(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_setlogin: /* setlogin(2) */
++ ret = do_bsd_setlogin(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_getlogin: /* getlogin(2) */
++ ret = do_bsd_getlogin(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_getrusage: /* getrusage(2) */
++ ret = do_bsd_getrusage(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_getrlimit: /* getrlimit(2) */
++ ret = do_bsd_getrlimit(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_setrlimit: /* setrlimit(2) */
++ ret = do_bsd_setrlimit(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_getpid: /* getpid(2) */
++ ret = do_bsd_getpid();
++ break;
++
++ case TARGET_FREEBSD_NR_getppid: /* getppid(2) */
++ ret = do_bsd_getppid();
++ break;
++
++ case TARGET_FREEBSD_NR_getuid: /* getuid(2) */
++ ret = do_bsd_getuid();
++ break;
++
++ case TARGET_FREEBSD_NR_geteuid: /* geteuid(2) */
++ ret = do_bsd_geteuid();
++ break;
++
++ case TARGET_FREEBSD_NR_getgid: /* getgid(2) */
++ ret = do_bsd_getgid();
++ break;
++
++ case TARGET_FREEBSD_NR_getegid: /* getegid(2) */
++ ret = do_bsd_getegid();
++ break;
++
++ case TARGET_FREEBSD_NR_setuid: /* setuid(2) */
++ ret = do_bsd_setuid(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_seteuid: /* seteuid(2) */
++ ret = do_bsd_seteuid(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_setgid: /* setgid(2) */
++ ret = do_bsd_setgid(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_setegid: /* setegid(2) */
++ ret = do_bsd_setegid(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_getpgrp: /* getpgrp(2) */
++ ret = do_bsd_getpgrp();
++ break;
++
++ case TARGET_FREEBSD_NR_setreuid: /* setreuid(2) */
++ ret = do_bsd_setreuid(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_setregid: /* setregid(2) */
++ ret = do_bsd_setregid(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_getresuid: /* getresuid(2) */
++ ret = do_bsd_getresuid(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getresgid: /* getresgid(2) */
++ ret = do_bsd_getresgid(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getsid: /* getsid(2) */
++ ret = do_bsd_getsid(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_setsid: /* setsid(2) */
++ ret = do_bsd_setsid();
++ break;
++
++ case TARGET_FREEBSD_NR_issetugid: /* issetugid(2) */
++ ret = do_bsd_issetugid();
++ break;
++
++ case TARGET_FREEBSD_NR_profil: /* profil(2) */
++ ret = do_bsd_profil(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_ktrace: /* ktrace(2) */
++ ret = do_bsd_ktrace(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_setloginclass: /* setloginclass(2) */
++ ret = do_freebsd_setloginclass(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_getloginclass: /* getloginclass(2) */
++ ret = do_freebsd_getloginclass(arg1, arg2);
++ break;
++
++#if 0
++ case TARGET_FREEBSD_NR_pdwait4: /* pdwait4(2) */
++ ret = do_freebsd_pdwait4(arg1, arg2, arg3, arg4);
++ break;
++#endif
++
++ case TARGET_FREEBSD_NR_pdgetpid: /* pdgetpid(2) */
++ ret = do_freebsd_pdgetpid(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR___setugid: /* undocumented */
++ ret = do_freebsd___setugid(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_jail: /* jail(2) */
++ ret = do_freebsd_jail(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_jail_attach: /* jail_attach(2) */
++ ret = do_freebsd_jail_attach(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_jail_remove: /* jail_remove(2) */
++ ret = do_freebsd_jail_remove(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_jail_get: /* jail_get(2) */
++ ret = do_freebsd_jail_get(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_jail_set: /* jail_set(2) */
++ ret = do_freebsd_jail_set(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_cap_enter: /* cap_enter(2) */
++ ret = do_freebsd_cap_enter();
++ break;
++
++ case TARGET_FREEBSD_NR_cap_new: /* cap_new(2) */
++ ret = do_freebsd_cap_new(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_cap_getrights: /* cap_getrights(2) */
++ ret = do_freebsd_cap_getrights(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_cap_getmode: /* cap_getmode(2) */
++ ret = do_freebsd_cap_getmode(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_audit: /* audit(2) */
++ ret = do_freebsd_audit(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_auditon: /* auditon(2) */
++ ret = do_freebsd_auditon(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getaudit: /* getaudit(2) */
++ ret = do_freebsd_getaudit(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_setaudit: /* setaudit(2) */
++ ret = do_freebsd_setaudit(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_getaudit_addr: /* getaudit_addr(2) */
++ ret = do_freebsd_getaudit_addr(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_setaudit_addr: /* setaudit_addr(2) */
++ ret = do_freebsd_setaudit_addr(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_auditctl: /* auditctl(2) */
++ ret = do_freebsd_auditctl(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_utrace: /* utrace(2) */
++ ret = do_bsd_utrace(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_ptrace: /* ptrace(2) */
++ ret = do_bsd_ptrace(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_getpriority: /* getpriority(2) */
++ ret = do_bsd_getpriority(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_setpriority: /* setpriority(2) */
++ ret = do_bsd_setpriority(arg1, arg2, arg3);
++ break;
++
++
++
++ /*
++ * File system calls.
++ */
++ case TARGET_FREEBSD_NR_read: /* read(2) */
++ ret = do_bsd_read(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_pread: /* pread(2) */
++ ret = do_bsd_pread(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_readv: /* readv(2) */
++ ret = do_bsd_read(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_write: /* write(2) */
++ ret = do_bsd_write(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_pwrite: /* pwrite(2) */
++ ret = do_bsd_pwrite(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_writev: /* writev(2) */
++ ret = do_bsd_writev(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_pwritev: /* pwritev(2) */
++ ret = do_bsd_pwritev(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_open: /* open(2) */
++ ret = do_bsd_open(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_openat: /* openat(2) */
++ ret = do_bsd_openat(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_close: /* close(2) */
++ ret = do_bsd_close(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_closefrom: /* closefrom(2) */
++ ret = do_bsd_closefrom(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_revoke: /* revoke(2) */
++ ret = do_bsd_revoke(arg1);
++ break;
++
++#ifdef TARGET_FREEBSD_NR_creat
++ case TARGET_FREEBSD_NR_creat: /* creat(2) (obsolete) */
++ ret = do_bsd_creat(arg1);
++ break;
++#endif
++
++ case TARGET_FREEBSD_NR_access: /* access(2) */
++ ret = do_bsd_access(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_eaccess: /* eaccess(2) */
++ ret = do_bsd_eaccess(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_faccessat: /* faccessat(2) */
++ ret = do_bsd_faccessat(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_chdir: /* chdir(2) */
++ ret = do_bsd_chdir(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_fchdir: /* fchdir(2) */
++ ret = do_bsd_fchdir(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_rename: /* rename(2) */
++ ret = do_bsd_rename(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_renameat: /* renameat(2) */
++ ret = do_bsd_renameat(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_link: /* link(2) */
++ ret = do_bsd_link(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_linkat: /* linkat(2) */
++ ret = do_bsd_linkat(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_unlink: /* unlink(2) */
++ ret = do_bsd_unlink(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_unlinkat: /* unlinkat(2) */
++ ret = do_bsd_unlinkat(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_mkdir: /* mkdir(2) */
++ ret = do_bsd_mkdir(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_mkdirat: /* mkdirat(2) */
++ ret = do_bsd_mkdirat(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_rmdir: /* rmdir(2) (XXX no rmdirat()?) */
++ ret = do_bsd_rmdir(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR___getcwd: /* undocumented __getcwd() */
++ ret = do_bsd___getcwd(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_dup: /* dup(2) */
++ ret = do_bsd_dup(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_dup2: /* dup2(2) */
++ ret = do_bsd_dup2(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_truncate: /* truncate(2) */
++ ret = do_bsd_truncate(cpu_env, arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_ftruncate: /* ftruncate(2) */
++ ret = do_bsd_ftruncate(cpu_env, arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_acct: /* acct(2) */
++ ret = do_bsd_acct(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_sync: /* sync(2) */
++ ret = do_bsd_sync();
++ break;
++
++ case TARGET_FREEBSD_NR_mount: /* mount(2) */
++ ret = do_bsd_mount(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_unmount: /* unmount(2) */
++ ret = do_bsd_unmount(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_nmount: /* nmount(2) */
++ ret = do_bsd_nmount(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_symlink: /* symlink(2) */
++ ret = do_bsd_symlink(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_symlinkat: /* symlinkat(2) */
++ ret = do_bsd_symlinkat(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_readlink: /* readlink(2) */
++ ret = do_bsd_readlink(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_readlinkat: /* readlinkat(2) */
++ ret = do_bsd_readlinkat(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_chmod: /* chmod(2) */
++ ret = do_bsd_chmod(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fchmod: /* fchmod(2) */
++ ret = do_bsd_fchmod(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_lchmod: /* lchmod(2) */
++ ret = do_bsd_lchmod(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fchmodat: /* fchmodat(2) */
++ ret = do_bsd_fchmodat(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_mknod: /* mknod(2) */
++ ret = do_bsd_mknod(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_mknodat: /* mknodat(2) */
++ ret = do_bsd_mknodat(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_chown: /* chown(2) */
++ ret = do_bsd_chown(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_fchown: /* fchown(2) */
++ ret = do_bsd_fchown(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_lchown: /* lchown(2) */
++ ret = do_bsd_lchown(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_fchownat: /* fchownat(2) */
++ ret = do_bsd_fchownat(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_chflags: /* chflags(2) */
++ ret = do_bsd_chflags(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_lchflags: /* lchflags(2) */
++ ret = do_bsd_lchflags(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fchflags: /* fchflags(2) */
++ ret = do_bsd_fchflags(arg2, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_chroot: /* chroot(2) */
++ ret = do_bsd_chroot(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_flock: /* flock(2) */
++ ret = do_bsd_flock(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_mkfifo: /* mkfifo(2) */
++ ret = do_bsd_mkfifo(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_mkfifoat: /* mkfifoat(2) */
++ ret = do_bsd_mkfifoat(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_pathconf: /* pathconf(2) */
++ ret = do_bsd_pathconf(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_lpathconf: /* lpathconf(2) */
++ ret = do_bsd_lpathconf(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fpathconf: /* fpathconf(2) */
++ ret = do_bsd_fpathconf(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_undelete: /* undelete(2) */
++ ret = do_bsd_undelete(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_poll: /* poll(2) */
++ ret = do_bsd_poll(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_openbsd_poll: /* undocumented openbsd_poll() */
++ ret = do_bsd_openbsd_poll(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_lseek: /* lseek(2) */
++ ret = do_bsd_lseek(cpu_env, arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_pipe: /* pipe(2) */
++ ret = do_bsd_pipe(cpu_env, arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_swapon: /* swapon(2) */
++ ret = do_bsd_swapon(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_swapoff: /* swapoff(2) */
++ ret = do_bsd_swapoff(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_freebsd6_pread: /* undocumented freebsd6_pread() */
++ ret = do_bsd_freebsd6_pread(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_freebsd6_pwrite: /* undocumented freebsd6_pwrite() */
++ ret = do_bsd_freebsd6_pwrite(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_freebsd6_lseek: /* undocumented freebsd6_lseek() */
++ ret = do_bsd_freebsd6_lseek(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_freebsd6_truncate: /* undocumented */
++ ret = do_bsd_freebsd6_truncate(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_freebsd6_ftruncate: /* undocumented */
++ ret = do_bsd_freebsd6_ftruncate(arg1, arg2, arg3);
++ break;
++
++ /*
++ * stat system calls
++ */
++ case TARGET_FREEBSD_NR_stat: /* stat(2) */
++ ret = do_freebsd_stat(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_lstat: /* lstat(2) */
++ ret = do_freebsd_lstat(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fstat: /* fstat(2) */
++ ret = do_freebsd_fstat(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fstatat: /* fstatat(2) */
++ ret = do_freebsd_fstatat(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_nstat: /* undocumented */
++ ret = do_freebsd_nstat(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_nfstat: /* undocumented */
++ ret = do_freebsd_nfstat(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_nlstat: /* undocumented */
++ ret = do_freebsd_nlstat(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_getfh: /* getfh(2) */
++ ret = do_freebsd_getfh(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_lgetfh: /* lgetfh(2) */
++ ret = do_freebsd_lgetfh(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fhopen: /* fhopen(2) */
++ ret = do_freebsd_fhopen(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fhstat: /* fhstat(2) */
++ ret = do_freebsd_fhstat(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fhstatfs: /* fhstatfs(2) */
++ ret = do_freebsd_fhstatfs(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_statfs: /* statfs(2) */
++ ret = do_freebsd_statfs(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_fstatfs: /* fstatfs(2) */
++ ret = do_freebsd_fstatfs(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_getfsstat: /* getfsstat(2) */
++ ret = do_freebsd_getfsstat(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getdents: /* getdents(2) */
++ ret = do_freebsd_getdents(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getdirentries: /* getdirentries(2) */
++ ret = do_freebsd_getdirentries(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_fcntl: /* fcntl(2) */
++ ret = do_freebsd_fcntl(arg1, arg2, arg3);
++ break;
++
++
++ /*
++ * Memory management system calls.
++ */
++ case TARGET_FREEBSD_NR_mmap: /* mmap(2) */
++ ret = do_bsd_mmap(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
++ arg8);
++ break;
++
++ case TARGET_FREEBSD_NR_munmap: /* munmap(2) */
++ ret = do_bsd_munmap(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_mprotect: /* mprotect(2) */
++ ret = do_bsd_mprotect(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_msync: /* msync(2) */
++ ret = do_bsd_msync(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_mlock: /* mlock(2) */
++ ret = do_bsd_mlock(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_munlock: /* munlock(2) */
++ ret = do_bsd_munlock(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_mlockall: /* mlockall(2) */
++ ret = do_bsd_mlockall(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_munlockall: /* munlockall(2) */
++ ret = do_bsd_munlockall();
++ break;
++
++ case TARGET_FREEBSD_NR_madvise: /* madvise(2) */
++ ret = do_bsd_madvise(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_minherit: /* minherit(2) */
++ ret = do_bsd_minherit(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_mincore: /* mincore(2) */
++ ret = do_bsd_mincore(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_shm_open: /* shm_open(2) */
++ ret = do_bsd_shm_open(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_shm_unlink: /* shm_unlink(2) */
++ ret = do_bsd_shm_unlink(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_shmget: /* shmget(2) */
++ ret = do_bsd_shmget(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_shmctl: /* shmctl(2) */
++ ret = do_bsd_shmctl(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_shmat: /* shmat(2) */
++ ret = do_bsd_shmat(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_shmdt: /* shmdt(2) */
++ ret = do_bsd_shmdt(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_vadvise:
++ ret = do_bsd_vadvise();
++ break;
++
++ case TARGET_FREEBSD_NR_sbrk:
++ ret = do_bsd_sbrk();
++ break;
++
++ case TARGET_FREEBSD_NR_sstk:
++ ret = do_bsd_sstk();
++ break;
++
++ case TARGET_FREEBSD_NR_freebsd6_mmap: /* undocumented */
++ ret = do_bsd_freebsd6_mmap(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
++ break;
++
++
++ /*
++ * time related system calls.
++ */
++ case TARGET_FREEBSD_NR_nanosleep: /* nanosleep(2) */
++ ret = do_freebsd_nanosleep(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_clock_gettime: /* clock_gettime(2) */
++ ret = do_freebsd_clock_gettime(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_clock_settime: /* clock_settime(2) */
++ ret = do_freebsd_clock_settime(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_clock_getres: /* clock_getres(2) */
++ ret = do_freebsd_clock_getres(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_gettimeofday: /* gettimeofday(2) */
++ ret = do_freebsd_gettimeofday(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_settimeofday: /* settimeofday(2) */
++ ret = do_freebsd_settimeofday(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_adjtime: /* adjtime(2) */
++ ret = do_freebsd_adjtime(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_ntp_adjtime: /* ntp_adjtime(2) */
++ ret = do_freebsd_ntp_adjtime(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_ntp_gettime: /* ntp_gettime(2) */
++ ret = do_freebsd_ntp_gettime(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_utimes: /* utimes(2) */
++ ret = do_freebsd_utimes(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_lutimes: /* lutimes(2) */
++ ret = do_freebsd_lutimes(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_futimes: /* futimes(2) */
++ ret = do_freebsd_futimes(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_futimesat: /* futimesat(2) */
++ ret = do_freebsd_futimesat(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_ktimer_create: /* undocumented */
++ ret = do_freebsd_ktimer_create(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_ktimer_delete: /* undocumented */
++ ret = do_freebsd_ktimer_delete(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_ktimer_settime: /* undocumented */
++ ret = do_freebsd_ktimer_settime(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_ktimer_gettime: /* undocumented */
++ ret = do_freebsd_ktimer_gettime(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_ktimer_getoverrun: /* undocumented */
++ ret = do_freebsd_ktimer_getoverrun(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_select: /* select(2) */
++ ret = do_freebsd_select(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_pselect: /* pselect(2) */
++ ret = do_freebsd_pselect(arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_kqueue: /* kqueue(2) */
++ ret = do_freebsd_kqueue();
++ break;
++
++ case TARGET_FREEBSD_NR_kevent: /* kevent(2) */
++ ret = do_freebsd_kevent(arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_setitimer: /* setitimer(2) */
++ ret = do_freebsd_setitimer(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getitimer: /* getitimer(2) */
++ ret = do_freebsd_getitimer(arg1, arg2);
++ break;
++
++ /*
++ * signal system calls
++ */
++ case TARGET_FREEBSD_NR_sigtimedwait: /* sigtimedwait(2) */
++ ret = do_freebsd_sigtimedwait(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_sigaction: /* sigaction(2) */
++ ret = do_bsd_sigaction(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_sigprocmask: /* sigprocmask(2) */
++ ret = do_bsd_sigprocmask(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_sigpending: /* sigpending(2) */
++ ret = do_bsd_sigpending(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_sigsuspend: /* sigsuspend(2) */
++ ret = do_bsd_sigsuspend(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_sigreturn: /* sigreturn(2) */
++ ret = do_bsd_sigreturn(cpu_env, arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_sigwait: /* sigwait(2) */
++ ret = do_bsd_sigwait(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_sigwaitinfo: /* sigwaitinfo(2) */
++ ret = do_bsd_sigwaitinfo(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_sigqueue: /* sigqueue(2) */
++ ret = do_bsd_sigqueue(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_sigaltstack: /* sigaltstack(2) */
++ ret = do_bsd_sigaltstack(cpu_env, arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_kill: /* kill(2) */
++ ret = do_bsd_kill(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_killpg: /* killpg(2) */
++ ret = do_bsd_killpg(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_pdkill: /* pdkill(2) */
++ ret = do_freebsd_pdkill(arg1, arg2);
++ break;
++
++ /*
++ * socket related system calls
++ */
++ case TARGET_FREEBSD_NR_accept: /* accept(2) */
++ ret = do_bsd_accept(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_bind: /* bind(2) */
++ ret = do_bsd_bind(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_connect: /* connect(2) */
++ ret = do_bsd_connect(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getpeername: /* getpeername(2) */
++ ret = do_bsd_getpeername(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getsockname: /* getsockname(2) */
++ ret = do_bsd_getsockname(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_getsockopt: /* getsockopt(2) */
++ ret = do_bsd_getsockopt(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_setsockopt: /* setsockopt(2) */
++ ret = do_bsd_setsockopt(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_listen: /* listen(2) */
++ ret = get_errno(listen(arg1, arg2));
++ break;
++
++ case TARGET_FREEBSD_NR_recvfrom: /* recvfrom(2) */
++ ret = do_bsd_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_recvmsg: /* recvmsg(2) */
++ ret = do_freebsd_recvmsg(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_sendmsg: /* sendmsg(2) */
++ ret = do_freebsd_sendmsg(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_sendto: /* sendto(2) */
++ ret = do_bsd_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_socket: /* socket(2) */
++ ret = do_bsd_socket(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_socketpair: /* socketpair(2) */
++ ret = do_bsd_socketpair(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_shutdown: /* shutdown(2) */
++ ret = do_bsd_shutdown(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_setfib: /* setfib(2) */
++ ret = do_freebsd_setfib(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_sctp_peeloff: /* sctp_peeloff(2) */
++ ret = do_freebsd_sctp_peeloff(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_sctp_generic_sendmsg: /* sctp_generic_sendmsg(2) */
++ ret = do_freebsd_sctp_generic_sendmsg(arg1, arg2, arg2, arg4, arg5,
++ arg6, arg7);
++ break;
++
++ case TARGET_FREEBSD_NR_sctp_generic_recvmsg: /* sctp_generic_recvmsg(2) */
++ ret = do_freebsd_sctp_generic_recvmsg(arg1, arg2, arg2, arg4, arg5,
++ arg6, arg7);
++ break;
++
++ case TARGET_FREEBSD_NR_sendfile: /* sendfile(2) */
++ ret = do_freebsd_sendfile(arg1, arg2, arg2, arg4, arg5, arg6, arg7,
++ arg8);
++ break;
++
++ case TARGET_FREEBSD_NR_freebsd4_sendfile: /* freebsd4_sendfile(2) */
++ ret = do_freebsd_freebsd4_sendfile(arg1, arg2, arg2, arg4, arg5,
++ arg6, arg7, arg8);
++ break;
++
++ /*
++ * thread system calls
++ */
++ case TARGET_FREEBSD_NR_thr_create: /* thr_create(2) */
++ ret = do_freebsd_thr_create(cpu_env, arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_new: /* thr_new(2) */
++ ret = do_freebsd_thr_new(cpu_env, arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_set_name: /* thr_set_name(2) */
++ ret = do_freebsd_thr_set_name(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_self: /* thr_self(2) */
++ ret = do_freebsd_thr_self(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_suspend: /* thr_suspend(2) */
++ ret = do_freebsd_thr_suspend(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_wake: /* thr_wake(2) */
++ ret = do_freebsd_thr_wake(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_kill: /* thr_kill(2) */
++ ret = do_freebsd_thr_kill(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_thr_kill2: /* thr_kill2(2) */
++ ret = do_freebsd_thr_kill2(arg1, arg2, arg3);
++ break;
+
+-static abi_ulong target_brk;
+-static abi_ulong target_original_brk;
++ case TARGET_FREEBSD_NR_thr_exit: /* thr_exit(2) */
++ ret = do_freebsd_thr_exit(cpu_env, arg1);
++ break;
+
+-static inline abi_long get_errno(abi_long ret)
+-{
+- if (ret == -1)
+- /* XXX need to translate host -> target errnos here */
+- return -(errno);
+- else
+- return ret;
+-}
++ case TARGET_FREEBSD_NR_rtprio_thread: /* rtprio_thread(2) */
++ ret = do_freebsd_rtprio_thread(arg1, arg2, arg3);
++ break;
+
+-#define target_to_host_bitmask(x, tbl) (x)
++ case TARGET_FREEBSD_NR_getcontext: /* getcontext(2) */
++ ret = do_freebsd_getcontext(cpu_env, arg1);
++ break;
+
+-static inline int is_error(abi_long ret)
+-{
+- return (abi_ulong)ret >= (abi_ulong)(-4096);
+-}
++ case TARGET_FREEBSD_NR_setcontext: /* setcontext(2) */
++ ret = do_freebsd_setcontext(cpu_env, arg1);
++ break;
+
+-void target_set_brk(abi_ulong new_brk)
+-{
+- target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
+-}
++ case TARGET_FREEBSD_NR_swapcontext: /* swapcontext(2) */
++ ret = do_freebsd_swapcontext(cpu_env, arg1, arg2);
++ break;
+
+-/* do_obreak() must return target errnos. */
+-static abi_long do_obreak(abi_ulong new_brk)
+-{
+- abi_ulong brk_page;
+- abi_long mapped_addr;
+- int new_alloc_size;
++ case TARGET_FREEBSD_NR__umtx_lock: /* undocumented */
++ ret = do_freebsd__umtx_lock(arg1);
++ break;
+
+- if (!new_brk)
+- return 0;
+- if (new_brk < target_original_brk)
+- return -TARGET_EINVAL;
++ case TARGET_FREEBSD_NR__umtx_unlock: /* undocumented */
++ ret = do_freebsd__umtx_unlock(arg1);
++ break;
+
+- brk_page = HOST_PAGE_ALIGN(target_brk);
++ case TARGET_FREEBSD_NR__umtx_op: /* undocumented */
++ ret = do_freebsd__umtx_op(arg1, arg2, arg3, arg4, arg5);
++ break;
+
+- /* If the new brk is less than this, set it and we're done... */
+- if (new_brk < brk_page) {
+- target_brk = new_brk;
+- return 0;
+- }
++ /*
++ * ioctl(2)
++ */
++ case TARGET_FREEBSD_NR_ioctl: /* ioctl(2) */
++ ret = do_bsd_ioctl(arg1, arg2, arg3);
++ break;
+
+- /* We need to allocate more memory after the brk... */
+- new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
+- mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
+- PROT_READ|PROT_WRITE,
+- MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0));
++ /*
++ * sys{ctl, arch, call}
++ */
++ case TARGET_FREEBSD_NR___sysctl: /* sysctl(3) */
++ ret = do_freebsd_sysctl(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
+
+- if (!is_error(mapped_addr))
+- target_brk = new_brk;
+- else
+- return mapped_addr;
++ case TARGET_FREEBSD_NR_sysarch: /* sysarch(2) */
++ ret = do_freebsd_sysarch(cpu_env, arg1, arg2);
++ break;
+
+- return 0;
+-}
++ case TARGET_FREEBSD_NR_syscall: /* syscall(2) */
++ case TARGET_FREEBSD_NR___syscall: /* __syscall(2) */
++ ret = do_freebsd_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4,
++ arg5, arg6, arg7, arg8, 0);
++ break;
+
+-#if defined(TARGET_I386)
+-static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms)
+-{
+- abi_long ret = 0;
+- abi_ulong val;
+- int idx;
+-
+- switch(op) {
+-#ifdef TARGET_ABI32
+- case TARGET_FREEBSD_I386_SET_GSBASE:
+- case TARGET_FREEBSD_I386_SET_FSBASE:
+- if (op == TARGET_FREEBSD_I386_SET_GSBASE)
+-#else
+- case TARGET_FREEBSD_AMD64_SET_GSBASE:
+- case TARGET_FREEBSD_AMD64_SET_FSBASE:
+- if (op == TARGET_FREEBSD_AMD64_SET_GSBASE)
+-#endif
+- idx = R_GS;
+- else
+- idx = R_FS;
+- if (get_user(val, parms, abi_ulong))
+- return -TARGET_EFAULT;
+- cpu_x86_load_seg(env, idx, 0);
+- env->segs[idx].base = val;
+- break;
+-#ifdef TARGET_ABI32
+- case TARGET_FREEBSD_I386_GET_GSBASE:
+- case TARGET_FREEBSD_I386_GET_FSBASE:
+- if (op == TARGET_FREEBSD_I386_GET_GSBASE)
+-#else
+- case TARGET_FREEBSD_AMD64_GET_GSBASE:
+- case TARGET_FREEBSD_AMD64_GET_FSBASE:
+- if (op == TARGET_FREEBSD_AMD64_GET_GSBASE)
+-#endif
+- idx = R_GS;
+- else
+- idx = R_FS;
+- val = env->segs[idx].base;
+- if (put_user(val, parms, abi_ulong))
+- return -TARGET_EFAULT;
+- break;
+- /* XXX handle the others... */
+- default:
+- ret = -TARGET_EINVAL;
++ /*
++ * extended attributes system calls
++ */
++ case TARGET_FREEBSD_NR_extattrctl: /* extattrctl() */
++ ret = do_freebsd_extattrctl(arg1, arg2, arg3, arg4, arg5);
+ break;
+- }
+- return ret;
+-}
+-#endif
+
+-#ifdef TARGET_SPARC
+-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;
+-}
+-#endif
++ case TARGET_FREEBSD_NR_extattr_set_file: /* extattr_set_file(2) */
++ ret = do_freebsd_extattr_set_file(arg1, arg2, arg3, arg4, arg4);
++ break;
+
+-#ifdef __FreeBSD__
+-/*
+- * XXX this uses the undocumented oidfmt interface to find the kind of
+- * a requested sysctl, see /sys/kern/kern_sysctl.c:sysctl_sysctl_oidfmt()
+- * (this is mostly copied from src/sbin/sysctl/sysctl.c)
+- */
+-static int
+-oidfmt(int *oid, int len, char *fmt, uint32_t *kind)
+-{
+- int qoid[CTL_MAXNAME+2];
+- uint8_t buf[BUFSIZ];
+- int i;
+- size_t j;
++ case TARGET_FREEBSD_NR_extattr_get_file: /* extattr_get_file(2) */
++ ret = do_freebsd_extattr_get_file(arg1, arg2, arg3, arg4, arg4);
++ break;
+
+- qoid[0] = 0;
+- qoid[1] = 4;
+- memcpy(qoid + 2, oid, len * sizeof(int));
++ case TARGET_FREEBSD_NR_extattr_delete_file: /* extattr_delete_file(2) */
++ ret = do_freebsd_extattr_delete_file(arg1, arg2, arg3);
++ break;
+
+- j = sizeof(buf);
+- i = sysctl(qoid, len + 2, buf, &j, 0, 0);
+- if (i)
+- return i;
++ case TARGET_FREEBSD_NR_extattr_set_fd: /* extattr_set_fd(2) */
++ ret = do_freebsd_extattr_set_fd(arg1, arg2, arg3, arg4, arg5);
++ break;
+
+- if (kind)
+- *kind = *(uint32_t *)buf;
++ case TARGET_FREEBSD_NR_extattr_get_fd: /* extattr_get_fd(2) */
++ ret = do_freebsd_extattr_get_fd(arg1, arg2, arg3, arg4, arg5);
++ break;
+
+- if (fmt)
+- strcpy(fmt, (char *)(buf + sizeof(uint32_t)));
+- return (0);
+-}
++ case TARGET_FREEBSD_NR_extattr_delete_fd: /* extattr_delete_fd(2) */
++ ret = do_freebsd_extattr_delete_fd(arg1, arg2, arg3);
++ break;
+
+-/*
+- * try and convert sysctl return data for the target.
+- * XXX doesn't handle CTLTYPE_OPAQUE and CTLTYPE_STRUCT.
+- */
+-static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind)
+-{
+- switch (kind & CTLTYPE) {
+- case CTLTYPE_INT:
+- case CTLTYPE_UINT:
+- *(uint32_t *)holdp = tswap32(*(uint32_t *)holdp);
+- break;
+-#ifdef TARGET_ABI32
+- case CTLTYPE_LONG:
+- case CTLTYPE_ULONG:
+- *(uint32_t *)holdp = tswap32(*(long *)holdp);
+- break;
+-#else
+- case CTLTYPE_LONG:
+- *(uint64_t *)holdp = tswap64(*(long *)holdp);
+- case CTLTYPE_ULONG:
+- *(uint64_t *)holdp = tswap64(*(unsigned long *)holdp);
++ case TARGET_FREEBSD_NR_extattr_get_link: /* extattr_get_link(2) */
++ ret = do_freebsd_extattr_get_link(arg1, arg2, arg3, arg4, arg4);
+ break;
+-#endif
+-#ifdef CTLTYPE_U64
+- case CTLTYPE_S64:
+- case CTLTYPE_U64:
+-#else
+- case CTLTYPE_QUAD:
+-#endif
+- *(uint64_t *)holdp = tswap64(*(uint64_t *)holdp);
++
++ case TARGET_FREEBSD_NR_extattr_set_link: /* extattr_set_link(2) */
++ ret = do_freebsd_extattr_set_link(arg1, arg2, arg3, arg4, arg4);
+ break;
+- case CTLTYPE_STRING:
++
++ case TARGET_FREEBSD_NR_extattr_delete_link: /* extattr_delete_link(2) */
++ ret = do_freebsd_extattr_delete_link(arg1, arg2, arg3);
+ break;
+- default:
+- /* XXX unhandled */
+- return -1;
+- }
+- return 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;
+- size_t holdlen;
+- abi_ulong oldlen = 0;
+- int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i;
+- uint32_t kind = 0;
+-
+- if (oldlenp)
+- get_user_ual(oldlen, oldlenp);
+- 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)))
+- return -TARGET_EFAULT;
+- holdlen = oldlen;
+- for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++)
+- *q++ = tswap32(*p);
+- oidfmt(snamep, namelen, NULL, &kind);
+- /* XXX swap hnewp */
+- ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen));
+- if (!ret)
+- sysctl_oldcvt(holdp, holdlen, kind);
+- put_user_ual(holdlen, oldlenp);
+- unlock_user(hnamep, namep, 0);
+- unlock_user(holdp, oldp, holdlen);
+- if (hnewp)
+- unlock_user(hnewp, newp, 0);
+- g_free(snamep);
+- return ret;
+-}
+-#endif
++ case TARGET_FREEBSD_NR_extattr_list_fd: /* extattr_list_fd(2) */
++ ret = do_freebsd_extattr_list_fd(arg1, arg2, arg3, arg4);
++ break;
+
+-/* FIXME
+- * lock_iovec()/unlock_iovec() have a return code of 0 for success where
+- * other lock functions have a return code of 0 for failure.
+- */
+-static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
+- int count, int copy)
+-{
+- struct target_iovec *target_vec;
+- abi_ulong base;
+- int i;
++ case TARGET_FREEBSD_NR_extattr_list_file: /* extattr_list_file(2) */
++ ret = do_freebsd_extattr_list_file(arg1, arg2, arg3, arg4);
++ break;
+
+- target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
+- if (!target_vec)
+- return -TARGET_EFAULT;
+- for(i = 0;i < count; i++) {
+- base = tswapl(target_vec[i].iov_base);
+- vec[i].iov_len = tswapl(target_vec[i].iov_len);
+- if (vec[i].iov_len != 0) {
+- vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
+- /* Don't check lock_user return value. We must call writev even
+- if a element has invalid base address. */
+- } else {
+- /* zero length pointer is ignored */
+- vec[i].iov_base = NULL;
+- }
+- }
+- unlock_user (target_vec, target_addr, 0);
+- return 0;
+-}
++ case TARGET_FREEBSD_NR_extattr_list_link: /* extattr_list_link(2) */
++ ret = do_freebsd_extattr_list_link(arg1, arg2, arg3, arg4);
++ break;
+
+-static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
+- int count, int copy)
+-{
+- struct target_iovec *target_vec;
+- abi_ulong base;
+- int i;
++ case TARGET_FREEBSD_NR___acl_aclcheck_fd: /* __acl_aclcheck_fd() */
++ ret = do_freebsd__acl_aclcheck_fd(arg1, arg2, arg3);
++ break;
+
+- target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
+- if (!target_vec)
+- return -TARGET_EFAULT;
+- for(i = 0;i < count; i++) {
+- if (target_vec[i].iov_base) {
+- base = tswapl(target_vec[i].iov_base);
+- unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
+- }
+- }
+- unlock_user (target_vec, target_addr, 0);
++ case TARGET_FREEBSD_NR___acl_aclcheck_file: /* __acl_aclcheck_file() */
++ ret = do_freebsd__acl_aclcheck_file(arg1, arg2, arg3);
++ break;
+
+- return 0;
+-}
++ case TARGET_FREEBSD_NR___acl_aclcheck_link: /* __acl_aclcheck_link() */
++ ret = do_freebsd__acl_aclcheck_link(arg1, arg2, arg3);
++ break;
+
+-/* 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;
++ case TARGET_FREEBSD_NR___acl_delete_fd: /* __acl_delete_fd() */
++ ret = do_freebsd__acl_delete_fd(arg1, arg2);
++ break;
+
+-#ifdef DEBUG
+- gemu_log("freebsd syscall %d\n", num);
+-#endif
+- if(do_strace)
+- print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
++ case TARGET_FREEBSD_NR___acl_delete_file: /* __acl_delete_file() */
++ ret = do_freebsd__acl_delete_file(arg1, arg2);
++ break;
+
+- 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_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);
+- }
++ case TARGET_FREEBSD_NR___acl_delete_link: /* __acl_delete_link() */
++ ret = do_freebsd__acl_delete_link(arg1, arg2);
+ 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);
++
++ case TARGET_FREEBSD_NR___acl_get_fd: /* __acl_get_fd() */
++ ret = do_freebsd__acl_get_fd(arg1, arg2, arg3);
+ break;
+- case TARGET_FREEBSD_NR_mmap:
+- ret = get_errno(target_mmap(arg1, arg2, arg3,
+- target_to_host_bitmask(arg4, mmap_flags_tbl),
+- arg5,
+- arg6));
++
++ case TARGET_FREEBSD_NR___acl_get_file: /* __acl_get_file() */
++ ret = do_freebsd__acl_get_file(arg1, arg2, arg3);
+ break;
+- case TARGET_FREEBSD_NR_mprotect:
+- ret = get_errno(target_mprotect(arg1, arg2, arg3));
++
++ case TARGET_FREEBSD_NR___acl_get_link: /* __acl_get_link() */
++ ret = do_freebsd__acl_get_link(arg1, arg2, arg3);
+ break;
+- case TARGET_FREEBSD_NR_break:
+- ret = do_obreak(arg1);
++
++ case TARGET_FREEBSD_NR___acl_set_fd: /* __acl_get_fd() */
++ ret = do_freebsd__acl_set_fd(arg1, arg2, arg3);
+ break;
+-#ifdef __FreeBSD__
+- case TARGET_FREEBSD_NR___sysctl:
+- ret = do_freebsd_sysctl(arg1, arg2, arg3, arg4, arg5, arg6);
++
++ case TARGET_FREEBSD_NR___acl_set_file: /* __acl_set_file() */
++ ret = do_freebsd__acl_set_file(arg1, arg2, arg3);
+ break;
+-#endif
+- case TARGET_FREEBSD_NR_sysarch:
+- ret = do_freebsd_sysarch(cpu_env, arg1, arg2);
++
++ case TARGET_FREEBSD_NR___acl_set_link: /* __acl_set_link() */
++ ret = do_freebsd__acl_set_link(arg1, arg2, arg3);
++ break;
++
++ /*
++ * SysV Semaphores
++ */
++ case TARGET_FREEBSD_NR_semget: /* semget(2) */
++ ret = do_bsd_semget(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_semop: /* semop(2) */
++ ret = do_bsd_semop(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR___semctl: /* __semctl() undocumented */
++ ret = do_bsd___semctl(arg1, arg2, arg3,
++ (union target_semun)(abi_ulong)arg4);
++ break;
++
++ /*
++ * SysV Messages
++ */
++ case TARGET_FREEBSD_NR_msgctl: /* msgctl(2) */
++ ret = do_bsd_msgctl(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_msgsnd: /* msgsnd(2) */
++ ret = do_bsd_msgsnd(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_msgrcv: /* msgrcv(2) */
++ ret = do_bsd_msgrcv(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ /*
++ * FreeBSD scheduler control
++ */
++ case TARGET_FREEBSD_NR_sched_setparam: /* sched_setparam(2) */
++ ret = do_freebsd_sched_setparam(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_sched_getparam: /* sched_getparam(2) */
++ ret = do_freebsd_sched_getparam(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_sched_setscheduler: /* sched_setscheduler(2) */
++ ret = do_freebsd_sched_setscheduler(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_sched_getscheduler: /* sched_getscheduler(2) */
++ ret = do_freebsd_sched_getscheduler(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_sched_rr_get_interval: /* sched_rr_get_interval(2) */
++ ret = do_freebsd_sched_rr_get_interval(arg1, arg2);
++ break;
++
++ /*
++ * FreeBSD CPU affinity sets management
++ */
++ case TARGET_FREEBSD_NR_cpuset: /* cpuset(2) */
++ ret = do_freebsd_cpuset(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_cpuset_setid: /* cpuset_setid(2) */
++ ret = do_freebsd_cpuset_setid(cpu_env, arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_cpuset_getid: /* cpuset_getid(2) */
++ ret = do_freebsd_cpuset_getid(arg1, arg2, arg3, arg4, arg5);
++ break;
++
++ case TARGET_FREEBSD_NR_cpuset_getaffinity: /* cpuset_getaffinity(2) */
++ ret = do_freebsd_cpuset_getaffinity(arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++ case TARGET_FREEBSD_NR_cpuset_setaffinity: /* cpuset_setaffinity(2) */
++ ret = do_freebsd_cpuset_setaffinity(arg1, arg2, arg3, arg4, arg5, arg6);
++ break;
++
++
++ /*
++ * FreeBSD kernel module
++ */
++ case TARGET_FREEBSD_NR_modfnext: /* modfnext(2) */
++ ret = do_freebsd_modfnext(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_modfind: /* modfind(2) */
++ ret = do_freebsd_modfind(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_kldload: /* kldload(2) */
++ ret = do_freebsd_kldload(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_kldunload: /* kldunload(2) */
++ ret = do_freebsd_kldunload(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_kldunloadf: /* kldunloadf(2) */
++ ret = do_freebsd_kldunloadf(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_kldfind: /* kldfind(2) */
++ ret = do_freebsd_kldfind(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_kldnext: /* kldnext(2) */
++ ret = do_freebsd_kldnext(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_kldstat: /* kldstat(2) */
++ ret = do_freebsd_kldstat(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_kldfirstmod: /* kldfirstmod(2) */
++ ret = do_freebsd_kldfirstmod(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_kldsym: /* kldsym(2) */
++ ret = do_freebsd_kldsym(arg1, arg2, arg3);
++ break;
++
++ /*
++ * FreeBSD resource controls (undocumented except for rctl(8)
++ * and rctl.conf(5) )
++ */
++ case TARGET_FREEBSD_NR_rctl_get_racct: /* rctl_get_racct() */
++ ret = do_freebsd_rctl_get_racct(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_rctl_get_rules: /* rctl_get_rules() */
++ ret = do_freebsd_rctl_get_rules(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_rctl_add_rule: /* rctl_add_rule() */
++ ret = do_freebsd_rctl_add_rule(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_rctl_remove_rule: /* rctl_remove_rule() */
++ ret = do_freebsd_rctl_remove_rule(arg1, arg2, arg3, arg4);
++ break;
++
++ case TARGET_FREEBSD_NR_rctl_get_limits: /* rctl_get_limits() */
++ ret = do_freebsd_rctl_get_limits(arg1, arg2, arg3, arg4);
++ break;
++
++ /*
++ * FreeBSD Mandatory Access Control
++ */
++ case TARGET_FREEBSD_NR___mac_get_proc: /* __mac_get_proc() */
++ ret = do_freebsd___mac_get_proc(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR___mac_set_proc: /* __mac_set_proc() */
++ ret = do_freebsd___mac_set_proc(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR___mac_get_fd: /* __mac_get_fd() */
++ ret = do_freebsd___mac_get_fd(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR___mac_set_fd: /* __mac_set_fd() */
++ ret = do_freebsd___mac_set_fd(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR___mac_get_file: /* __mac_get_file() */
++ ret = do_freebsd___mac_get_proc(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR___mac_set_file: /* __mac_set_file() */
++ ret = do_freebsd___mac_set_file(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR___mac_get_link: /* __mac_get_link() */
++ ret = do_freebsd___mac_get_link(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR___mac_set_link: /* __mac_set_link() */
++ ret = do_freebsd___mac_set_link(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_mac_syscall: /* mac_syscall() */
++ ret = do_freebsd_mac_syscall(arg1, arg2, arg3);
++ break;
++
++ /*
++ * FreeBSD additional posix support
++ */
++ case TARGET_FREEBSD_NR_posix_fallocate: /* posix_fallocate(2) */
++ ret = do_freebsd_posix_fallocate(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_posix_openpt: /* posix_fallocate(2) */
++ ret = do_freebsd_posix_openpt(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_posix_fadvise: /* posix_fadvise(2) */
++ ret = do_freebsd_posix_fadvise(arg1, arg2, arg3, arg4);
++ break;
++
++ /*
++ * Misc
++ */
++ case TARGET_FREEBSD_NR_quotactl: /* quotactl(2) */
++ ret = do_bsd_quotactl(arg1, arg2, arg3);
++ break;
++
++ case TARGET_FREEBSD_NR_reboot: /* reboot(2) */
++ ret = do_bsd_reboot(arg1);
++ break;
++
++ case TARGET_FREEBSD_NR_uuidgen: /* uuidgen(2) */
++ ret = do_bsd_uuidgen(arg1, arg2);
++ break;
++
++ case TARGET_FREEBSD_NR_getdtablesize: /* getdtablesize(2) */
++ ret = do_bsd_getdtablesize();
++ break;
++
++ case TARGET_FREEBSD_NR_kenv: /* kenv(2) */
++ ret = do_freebsd_kenv(arg1, arg2, arg2, arg4);
+ 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);
++
++
++ case TARGET_FREEBSD_NR_break:
++ ret = do_obreak(arg1);
+ break;
++
+ default:
+- ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
++ ret = get_errno(syscall(num, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
++ arg8));
+ break;
+ }
+- fail:
++
+ #ifdef DEBUG
+ gemu_log(" = %ld\n", ret);
+ #endif
+ if (do_strace)
+ print_freebsd_syscall_ret(num, ret);
+ return ret;
+- efault:
+- ret = -TARGET_EFAULT;
+- goto fail;
+ }
+
+ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
+@@ -420,7 +1556,6 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
+ abi_long arg5, abi_long arg6)
+ {
+ abi_long ret;
+- void *p;
+
+ #ifdef DEBUG
+ gemu_log("netbsd syscall %d\n", num);
+@@ -430,43 +1565,26 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
+
+ switch(num) {
+ case TARGET_NETBSD_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 */
++ ret = do_bsd_exit(cpu_env, arg1);
+ break;
++
+ case TARGET_NETBSD_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);
++ ret = do_bsd_read(arg1, arg2, arg3);
+ break;
+ case TARGET_NETBSD_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);
++ ret = do_bsd_write(arg1, arg2, arg3);
+ break;
+ case TARGET_NETBSD_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);
++ ret = do_bsd_open(arg1, arg2, arg3);
+ break;
++
+ case TARGET_NETBSD_NR_mmap:
+- ret = get_errno(target_mmap(arg1, arg2, arg3,
+- target_to_host_bitmask(arg4, mmap_flags_tbl),
+- arg5,
+- arg6));
++ ret = do_bsd_mmap(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6, 0, 0);
+ break;
+ case TARGET_NETBSD_NR_mprotect:
+- ret = get_errno(target_mprotect(arg1, arg2, arg3));
++ ret = do_bsd_mprotect(arg1, arg2, arg3);
+ break;
++
+ case TARGET_NETBSD_NR_syscall:
+ case TARGET_NETBSD_NR___syscall:
+ ret = do_netbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
+@@ -475,16 +1593,12 @@ abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
+ ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
+ }
+- fail:
+ #ifdef DEBUG
+ gemu_log(" = %ld\n", ret);
+ #endif
+ if (do_strace)
+ print_netbsd_syscall_ret(num, ret);
+ return ret;
+- efault:
+- ret = -TARGET_EFAULT;
+- goto fail;
+ }
+
+ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
+@@ -492,7 +1606,6 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
+ abi_long arg5, abi_long arg6)
+ {
+ abi_long ret;
+- void *p;
+
+ #ifdef DEBUG
+ gemu_log("openbsd syscall %d\n", num);
+@@ -502,43 +1615,26 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
+
+ switch(num) {
+ case TARGET_OPENBSD_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 */
++ ret = do_bsd_exit(cpu_env, arg1);
+ break;
++
+ case TARGET_OPENBSD_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);
++ ret = do_bsd_read(arg1, arg2, arg3);
+ break;
+ case TARGET_OPENBSD_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);
++ ret = do_bsd_write(arg1, arg2, arg3);
+ break;
+ case TARGET_OPENBSD_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);
++ ret = do_bsd_open(arg1, arg2, arg3);
+ break;
++
+ case TARGET_OPENBSD_NR_mmap:
+- ret = get_errno(target_mmap(arg1, arg2, arg3,
+- target_to_host_bitmask(arg4, mmap_flags_tbl),
+- arg5,
+- arg6));
++ ret = do_bsd_mmap(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6, 0, 0);
+ break;
+ case TARGET_OPENBSD_NR_mprotect:
+- ret = get_errno(target_mprotect(arg1, arg2, arg3));
++ ret = do_bsd_mprotect(arg1, arg2, arg3);
+ break;
++
+ case TARGET_OPENBSD_NR_syscall:
+ case TARGET_OPENBSD_NR___syscall:
+ ret = do_openbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
+@@ -547,18 +1643,16 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
+ ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
+ }
+- fail:
+ #ifdef DEBUG
+ gemu_log(" = %ld\n", ret);
+ #endif
+ if (do_strace)
+ print_openbsd_syscall_ret(num, ret);
+ return ret;
+- efault:
+- ret = -TARGET_EFAULT;
+- goto fail;
+ }
+
+ void syscall_init(void)
+ {
++
++ init_bsd_ioctl();
+ }
+diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
+index 207ddee..13678d4 100644
+--- a/bsd-user/syscall_defs.h
++++ b/bsd-user/syscall_defs.h
+@@ -1,105 +1,5 @@
+-/* $OpenBSD: signal.h,v 1.19 2006/01/08 14:20:16 millert Exp $ */
+-/* $NetBSD: signal.h,v 1.21 1996/02/09 18:25:32 christos Exp $ */
+-
+-/*
+- * Copyright (c) 1982, 1986, 1989, 1991, 1993
+- * The Regents of the University of California. All rights reserved.
+- * (c) UNIX System Laboratories, Inc.
+- * All or some portions of this file are derived from material licensed
+- * to the University of California by American Telephone and Telegraph
+- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+- * the permission of UNIX System Laboratories, Inc.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions
+- * are met:
+- * 1. Redistributions of source code must retain the above copyright
+- * notice, this list of conditions and the following disclaimer.
+- * 2. Redistributions in binary form must reproduce the above copyright
+- * notice, this list of conditions and the following disclaimer in the
+- * documentation and/or other materials provided with the distribution.
+- * 3. Neither the name of the University nor the names of its contributors
+- * may be used to endorse or promote products derived from this software
+- * without specific prior written permission.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+- * SUCH DAMAGE.
+- *
+- * @(#)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 */
+-#define TARGET_SIGILL 4 /* illegal instruction (not reset when caught) */
+-#define TARGET_SIGTRAP 5 /* trace trap (not reset when caught) */
+-#define TARGET_SIGABRT 6 /* abort() */
+-#define TARGET_SIGIOT SIGABRT /* compatibility */
+-#define TARGET_SIGEMT 7 /* EMT instruction */
+-#define TARGET_SIGFPE 8 /* floating point exception */
+-#define TARGET_SIGKILL 9 /* kill (cannot be caught or ignored) */
+-#define TARGET_SIGBUS 10 /* bus error */
+-#define TARGET_SIGSEGV 11 /* segmentation violation */
+-#define TARGET_SIGSYS 12 /* bad argument to system call */
+-#define TARGET_SIGPIPE 13 /* write on a pipe with no one to read it */
+-#define TARGET_SIGALRM 14 /* alarm clock */
+-#define TARGET_SIGTERM 15 /* software termination signal from kill */
+-#define TARGET_SIGURG 16 /* urgent condition on IO channel */
+-#define TARGET_SIGSTOP 17 /* sendable stop signal not from tty */
+-#define TARGET_SIGTSTP 18 /* stop signal from tty */
+-#define TARGET_SIGCONT 19 /* continue a stopped process */
+-#define TARGET_SIGCHLD 20 /* to parent on child stop or exit */
+-#define TARGET_SIGTTIN 21 /* to readers pgrp upon background tty read */
+-#define TARGET_SIGTTOU 22 /* like TTIN for output if (tp->t_local&LTOSTOP) */
+-#define TARGET_SIGIO 23 /* input/output possible signal */
+-#define TARGET_SIGXCPU 24 /* exceeded CPU time limit */
+-#define TARGET_SIGXFSZ 25 /* exceeded file size limit */
+-#define TARGET_SIGVTALRM 26 /* virtual time alarm */
+-#define TARGET_SIGPROF 27 /* profiling time alarm */
+-#define TARGET_SIGWINCH 28 /* window size changes */
+-#define TARGET_SIGINFO 29 /* information request */
+-#define TARGET_SIGUSR1 30 /* user defined signal 1 */
+-#define TARGET_SIGUSR2 31 /* user defined signal 2 */
+-
+-/*
+- * 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_SA_ONSTACK 0x0001 /* take signal on signal stack */
+-#define TARGET_SA_RESTART 0x0002 /* restart system on signal return */
+-#define TARGET_SA_RESETHAND 0x0004 /* reset to SIG_DFL when taking signal */
+-#define TARGET_SA_NODEFER 0x0010 /* don't mask the signal we're delivering */
+-#define TARGET_SA_NOCLDWAIT 0x0020 /* don't create zombies (assign to pid 1) */
+-#define TARGET_SA_USERTRAMP 0x0100 /* do not bounce off kernel's sigtramp */
+-#define TARGET_SA_NOCLDSTOP 0x0008 /* do not generate SIGCHLD on child stop */
+-#define TARGET_SA_SIGINFO 0x0040 /* generate siginfo_t */
+-
+-/*
+- * Flags for sigprocmask:
+- */
+-#define TARGET_SIG_BLOCK 1 /* block specified signal set */
+-#define TARGET_SIG_UNBLOCK 2 /* unblock specified signal set */
+-#define TARGET_SIG_SETMASK 3 /* set specified signal set */
+-
+-#define TARGET_BADSIG SIG_ERR
+-
+-#define TARGET_SS_ONSTACK 0x0001 /* take signals on alternate stack */
+-#define TARGET_SS_DISABLE 0x0004 /* disable taking signals on alternate stack */
++#ifndef _SYSCALL_DEFS_H_
++#define _SYSCALL_DEFS_H_
+
+ #include "errno_defs.h"
+
+@@ -112,3 +12,759 @@ struct target_iovec {
+ abi_long iov_len; /* Number of bytes */
+ };
+
++/*
++ * sys/ipc.h
++ */
++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 */
++};
++
++#define TARGET_IPC_RMID 0 /* remove identifier */
++#define TARGET_IPC_SET 1 /* set options */
++#define TARGET_IPC_STAT 2 /* get options */
++
++/*
++ * sys/sem.h
++ */
++#define TARGET_GETNCNT 3 /* Return the value of semncnt {READ} */
++#define TARGET_GETPID 4 /* Return the value of sempid {READ} */
++#define TARGET_GETVAL 5 /* Return the value of semval {READ} */
++#define TARGET_GETALL 6 /* Return semvals into arg.array {READ} */
++#define TARGET_GETZCNT 7 /* Return the value of semzcnt {READ} */
++#define TARGET_SETVAL 8 /* Set the value of semval to arg.val {ALTER} */
++#define TARGET_SETALL 9 /* Set semvals from arg.array {ALTER} */
++#define TARGET_SEM_STAT 10 /* Like IPC_STAT but treats semid as sema-index */
++#define TARGET_SEM_INFO 11 /* Like IPC_INFO but treats semid as sema-index */
++
++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_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 */
++};
++
++/*
++ * sys/shm.h
++ */
++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() */
++};
++
++#define N_BSD_SHM_REGIONS 32
++struct bsd_shm_regions {
++ abi_long start;
++ abi_long size;
++};
++
++/*
++ * sys/msg.h
++ */
++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 */
++};
++
++/*
++ * sched.h
++ */
++struct target_sched_param {
++ int32_t sched_priority;
++};
++
++/*
++ * sys/mman.h
++ */
++#define TARGET_FREEBSD_MAP_RESERVED0080 0x0080 /* previously misimplemented
++ MAP_INHERIT */
++#define TARGET_FREEBSD_MAP_RESERVED0100 0x0100 /* previously unimplemented
++ MAP_NOEXTEND */
++#define TARGET_FREEBSD_MAP_STACK 0x0400 /* region grows down, like a
++ stack */
++#define TARGET_FREEBSD_MAP_NOSYNC 0x0800 /* page to but do not sync
++ underlying file */
++
++#define TARGET_FREEBSD_MAP_FLAGMASK 0x1ff7
++
++#define TARGET_NETBSD_MAP_INHERIT 0x0080 /* region is retained after
++ exec */
++#define TARGET_NETBSD_MAP_TRYFIXED 0x0400 /* attempt hint address, even
++ within break */
++#define TARGET_NETBSD_MAP_WIRED 0x0800 /* mlock() mapping when it is
++ established */
++
++#define TARGET_NETBSD_MAP_STACK 0x2000 /* allocated from memory, swap
++ space (stack) */
++
++#define TARGET_NETBSD_MAP_FLAGMASK 0x3ff7
++
++#define TARGET_OPENBSD_MAP_INHERIT 0x0080 /* region is retained after
++ exec */
++#define TARGET_OPENBSD_MAP_NOEXTEND 0x0100 /* for MAP_FILE, don't change
++ file size */
++#define TARGET_OPENBSD_MAP_TRYFIXED 0x0400 /* attempt hint address,
++ even within heap */
++
++#define TARGET_OPENBSD_MAP_FLAGMASK 0x17f7
++
++/* XXX */
++#define TARGET_BSD_MAP_FLAGMASK 0x3ff7
++
++/*
++ * sys/time.h
++ * sys/timex.h
++ */
++
++/*
++ * time_t seems to be very inconsistly defined for the different *BSD's...
++ *
++ * FreeBSD/{arm, mips} uses a 64bits time_t, even in 32bits mode,
++ * so we have to add a special case here.
++ *
++ * On NetBSD time_t is always defined as an int64_t. On OpenBSD time_t
++ * is always defined as an int.
++ *
++ */
++#if (defined(TARGET_ARM) || defined(TARGET_MIPS))
++typedef int64_t target_freebsd_time_t;
++#else
++typedef abi_long target_freebsd_time_t;
++#endif
++
++typedef abi_long target_freebsd_suseconds_t;
++
++/* compare to sys/timespec.h */
++struct target_freebsd_timespec {
++ target_freebsd_time_t tv_sec; /* seconds */
++ abi_long tv_nsec; /* and nanoseconds */
++#if (defined(TARGET_ARM) || defined(TARGET_MIPS)) && TARGET_ABI_BITS == 32
++ abi_long _pad;
++#endif
++} __packed;
++
++struct target_freebsd_timeval {
++ target_freebsd_time_t tv_sec; /* seconds */
++ target_freebsd_suseconds_t tv_usec;/* and microseconds */
++#if (defined(TARGET_ARM) || defined(TARGET_MIPS)) && TARGET_ABI_BITS == 32
++ abi_long _pad;
++#endif
++} __packed;
++
++/* compare to sys/timex.h */
++struct target_freebsd_ntptimeval {
++ struct target_freebsd_timespec time;
++ abi_long maxerror;
++ abi_long esterror;
++ abi_long tai;
++ int32_t time_state;
++};
++
++struct target_freebsd_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;
++};
++
++/*
++ * sys/event.h
++ */
++struct target_freebsd_kevent {
++ abi_ulong ident;
++ int16_t filter;
++ uint16_t flags;
++ uint32_t fflags;
++ abi_long data;
++ abi_ulong udata;
++} __packed;
++
++/*
++ * sys/resource.h
++ */
++#if defined(__FreeBSD__) && defined(TARGET_ALPHA)
++#define TARGET_RLIM_INFINITY 0x7fffffffffffffffull
++#elif defined(__FreeBSD__) && (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_rlimit {
++ uint64_t rlim_cur;
++ uint64_t rlim_max;
++};
++
++struct target_freebsd_rusage {
++ struct target_freebsd_timeval ru_utime; /* user time used */
++ struct target_freebsd_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 */
++};
++
++/*
++ * sys/socket.h
++ */
++
++/*
++ * 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
++
++struct target_msghdr {
++ abi_long msg_name; /* So cket name */
++ int32_t 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 */
++ int32_t msg_flags; /* flags on received message */
++};
++
++struct target_sockaddr {
++ 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 */
++};
++
++struct target_cmsghdr {
++ abi_long cmsg_len;
++ int32_t cmsg_level;
++ int32_t 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;
++}
++
++/*
++ * 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;
++};
++
++/*
++ * sys/stat.h
++ */
++#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
++
++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 last accessed */
++ struct target_freebsd_timespec st_mtim; /* time last data modification */
++ struct target_freebsd_timespec st_ctim; /* time 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 target_freebsd_timespec));
++ unsigned int:(8 / 2) * (16 - (int)sizeof(struct target_freebsd_timespec));
++} __packed;
++
++/* struct nstat is the same as stat above but without the st_lspare field */
++struct target_freebsd_nstat {
++ 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 last accessed */
++ struct target_freebsd_timespec st_mtim; /* time last data modification */
++ struct target_freebsd_timespec st_ctim; /* time 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 target_freebsd_timespec));
++ unsigned int:(8 / 2) * (16 - (int)sizeof(struct target_freebsd_timespec));
++} __packed;
++
++/*
++ * sys/mount.h
++ */
++
++/* filesystem id type */
++typedef struct target_freebsd_fsid { int32_t val[2]; } target_freebsd_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_freebsd_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 */
++ uint32_t f_owner; /* user that mounted the filesystem */
++ target_freebsd_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_freebsd_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_freebsd_fhandle {
++ target_freebsd_fsid_t fh_fsid; /* Filesystem id of mount point */
++ struct target_freebsd_fid fh_fid; /* Filesys specific id */
++};
++typedef struct target_freebsd_fhandle target_freebsd_fhandle_t;
++
++/*
++ * sys/fcntl.h
++ */
++#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_F_DUPFD_CLOEXEC 17
++#define TARGET_F_DUP2FD_CLOEXEC 18
++
++struct target_freebsd_flock {
++ int64_t l_start;
++ int64_t l_len;
++ int32_t l_pid;
++ int16_t l_type;
++ int16_t l_whence;
++ int32_t l_sysid;
++} QEMU_PACKED;
++
++/*
++ * FreeBSD thread and user mutex support.
++ */
++
++/* sys/thr.h */
++#define TARGET_THR_SUSPENDED 0x0001
++#define TARGET_THR_SYSTEM_SCOPE 0x0002
++
++struct target_freebsd_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. */
++ int32_t flags; /* thread flags. */
++ abi_ulong rtp; /* Real-time scheduling priority. */
++ abi_ulong spare[3]; /* spares. */
++};
++
++/* sys/rtprio.h */
++struct target_freebsd_rtprio {
++ uint16_t type;
++ uint16_t prio;
++};
++
++typedef struct {
++ CPUArchState *env;
++ long parent_tid;
++ pthread_mutex_t mutex;
++ pthread_cond_t cond;
++ pthread_t thread;
++ sigset_t sigmask;
++ struct target_freebsd_thr_param param;
++} new_freebsd_thread_info_t;
++
++/* 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_MUTEX_WAKE2 22
++#define TARGET_UMTX_OP_MAX 23
++
++/* flags for UMTX_OP_CV_WAIT */
++#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_ulong)(-1)
++#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)
++
++/*
++ * sys/acl.h
++ */
++#define TARGET_FREEBSD_ACL_MAX_ENTRIES 254
++
++/* vaild acl_type_t arguments */
++#define TARGET_FREEBSD_ACL_TYPE_ACCESS_OLD 0x00000000
++#define TARGET_FREEBSD_ACL_TYPE_DEFAULT_OLD 0x00000001
++#define TARGET_FREEBSD_ACL_TYPE_ACCESS 0x00000002
++#define TARGET_FREEBSD_ACL_TYPE_DEFAULT 0x00000003
++#define TARGET_FREEBSD_ACL_TYPE_NFS4 0x00000004
++
++struct target_freebsd_acl_entry {
++ uint32_t ae_tag;
++ uint32_t ae_id;
++ uint32_t ae_perm;
++ uint16_t ae_entry_type;
++ uint16_t ae_flags;
++};
++
++struct target_freebsd_acl {
++ uint32_t acl_maxcnt;
++ uint32_t acl_cnt;
++ int32_t acl_spare[4];
++ struct target_freebsd_acl_entry acl_entry[TARGET_FREEBSD_ACL_MAX_ENTRIES];
++};
++
++/*
++ * 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];
++};
++
++
++/*
++ * from personality.h
++ */
++
++/*
++ * Flags for bug emulation.
++ *
++ * These occupy the top three bytes.
++ */
++enum {
++ ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA
++ space */
++ FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs
++ point to descriptors
++ (signal handling) */
++ MMAP_PAGE_ZERO = 0x0100000,
++ ADDR_COMPAT_LAYOUT = 0x0200000,
++ READ_IMPLIES_EXEC = 0x0400000,
++ ADDR_LIMIT_32BIT = 0x0800000,
++ SHORT_INODE = 0x1000000,
++ WHOLE_SECONDS = 0x2000000,
++ STICKY_TIMEOUTS = 0x4000000,
++ ADDR_LIMIT_3GB = 0x8000000,
++};
++
++/*
++ * Personality types.
++ *
++ * These go in the low byte. Avoid using the top bit, it will
++ * conflict with error returns.
++ */
++enum {
++ PER_LINUX = 0x0000,
++ PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
++ PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
++ PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
++ PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
++ PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS |
++ WHOLE_SECONDS | SHORT_INODE,
++ PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
++ PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
++ PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
++ PER_BSD = 0x0006,
++ PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
++ PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
++ PER_LINUX32 = 0x0008,
++ PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
++ PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
++ PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
++ PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
++ PER_RISCOS = 0x000c,
++ PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
++ PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
++ PER_OSF4 = 0x000f, /* OSF/1 v4 */
++ PER_HPUX = 0x0010,
++ PER_MASK = 0x00ff,
++};
++
++/*
++ * Return the base personality without flags.
++ */
++#define personality(pers) (pers & PER_MASK)
++
++#endif /* ! _SYSCALL_DEFS_H_ */
+diff --git a/bsd-user/x86_64/syscall.h b/bsd-user/x86_64/syscall.h
+index 630514a..4fff6a5 100644
+--- a/bsd-user/x86_64/syscall.h
++++ b/bsd-user/x86_64/syscall.h
+@@ -1,3 +1,23 @@
++/*
++ * x86_64 system call definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _X86_64_SYSCALL_H_
++#define _X86_64_SYSCALL_H_
++
+ #define __USER_CS (0x33)
+ #define __USER_DS (0x2B)
+
+@@ -108,9 +128,13 @@ struct target_msqid64_ds {
+ #define TARGET_FREEBSD_AMD64_SET_GSBASE 131
+
+
+-#define UNAME_MACHINE "x86_64"
++#define UNAME_MACHINE "x86_64"
++#define TARGET_HW_MACHINE "amd64"
++#define TARGET_HW_MACHINE_ARCH "amd64"
+
+ #define TARGET_ARCH_SET_GS 0x1001
+ #define TARGET_ARCH_SET_FS 0x1002
+ #define TARGET_ARCH_GET_FS 0x1003
+ #define TARGET_ARCH_GET_GS 0x1004
++
++#endif /* ! _X86_64_SYSCALL_H_ */
+diff --git a/bsd-user/x86_64/target_arch.h b/bsd-user/x86_64/target_arch.h
+new file mode 100644
+index 0000000..7fe81dc
+--- /dev/null
++++ b/bsd-user/x86_64/target_arch.h
+@@ -0,0 +1,13 @@
++
++#ifndef _TARGET_ARCH_H_
++#define _TARGET_ARCH_H_
++
++/* target_arch_cpu.c */
++void bsd_x86_64_write_dt(void *ptr, unsigned long addr, unsigned long limit,
++ int flags);
++void bsd_x86_64_set_idt(int n, unsigned int dpl);
++void bsd_x86_64_set_idt_base(uint64_t base);
++
++#define target_cpu_set_tls(env, newtls)
++
++#endif /* !_TARGET_ARCH_H_ */
+diff --git a/bsd-user/x86_64/target_arch_cpu.c b/bsd-user/x86_64/target_arch_cpu.c
+new file mode 100644
+index 0000000..5cfdfca
+--- /dev/null
++++ b/bsd-user/x86_64/target_arch_cpu.c
+@@ -0,0 +1,79 @@
++/*
++ * x86_64 cpu related code
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include <sys/types.h>
++
++#include "cpu.h"
++#include "qemu.h"
++#include "qemu/timer.h"
++
++#include "target_arch.h"
++
++static uint64_t *idt_table;
++
++/* CPUX86 core interface */
++void cpu_smm_update(CPUX86State *env)
++{
++}
++
++uint64_t cpu_get_tsc(CPUX86State *env)
++{
++ return cpu_get_real_ticks();
++}
++
++int cpu_get_pic_interrupt(CPUX86State *env)
++{
++ return -1;
++}
++
++void bsd_x86_64_write_dt(void *ptr, unsigned long addr,
++ unsigned long limit, int flags)
++{
++ unsigned int e1, e2;
++ uint32_t *p;
++ e1 = (addr << 16) | (limit & 0xffff);
++ e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
++ e2 |= flags;
++ p = ptr;
++ p[0] = tswap32(e1);
++ p[1] = tswap32(e2);
++}
++
++static void set_gate64(void *ptr, unsigned int type, unsigned int dpl,
++ uint64_t addr, unsigned int sel)
++{
++ uint32_t *p, e1, e2;
++ e1 = (addr & 0xffff) | (sel << 16);
++ e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
++ p = ptr;
++ p[0] = tswap32(e1);
++ p[1] = tswap32(e2);
++ p[2] = tswap32(addr >> 32);
++ p[3] = 0;
++}
++
++/* only dpl matters as we do only user space emulation */
++void bsd_x86_64_set_idt(int n, unsigned int dpl)
++{
++ set_gate64(idt_table + n * 2, 0, dpl, 0, 0);
++}
++
++void bsd_x86_64_set_idt_base(uint64_t base)
++{
++ idt_table = g2h(base);
++}
+diff --git a/bsd-user/x86_64/target_arch_cpu.h b/bsd-user/x86_64/target_arch_cpu.h
+new file mode 100644
+index 0000000..9a66b67
+--- /dev/null
++++ b/bsd-user/x86_64/target_arch_cpu.h
+@@ -0,0 +1,324 @@
++/*
++ * x86_64 cpu init and loop
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef _TARGET_ARCH_CPU_H_
++#define _TARGET_ARCH_CPU_H_
++
++#include "target_arch.h"
++
++#define TARGET_DEFAULT_CPU_MODEL "qemu64"
++
++#define TARGET_CPU_RESET(env)
++
++static inline void target_cpu_init(CPUX86State *env,
++ struct target_pt_regs *regs)
++{
++ uint64_t *gdt_table;
++
++ cpu_x86_set_cpl(env, 3);
++
++ env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
++ env->hflags |= HF_PE_MASK;
++ if (env->features[FEAT_1_EDX] & CPUID_SSE) {
++ env->cr[4] |= CR4_OSFXSR_MASK;
++ env->hflags |= HF_OSFXSR_MASK;
++ }
++
++ /* enable 64 bit mode if possible */
++ if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) {
++ fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n");
++ exit(1);
++ }
++ env->cr[4] |= CR4_PAE_MASK;
++ env->efer |= MSR_EFER_LMA | MSR_EFER_LME;
++ env->hflags |= HF_LMA_MASK;
++
++ /* flags setup : we activate the IRQs by default as in user mode */
++ env->eflags |= IF_MASK;
++
++ /* register setup */
++ env->regs[R_EAX] = regs->rax;
++ env->regs[R_EBX] = regs->rbx;
++ env->regs[R_ECX] = regs->rcx;
++ env->regs[R_EDX] = regs->rdx;
++ env->regs[R_ESI] = regs->rsi;
++ env->regs[R_EDI] = regs->rdi;
++ env->regs[R_EBP] = regs->rbp;
++ env->regs[R_ESP] = regs->rsp;
++ env->eip = regs->rip;
++
++ /* interrupt setup */
++ env->idt.limit = 511;
++
++ env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
++ PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
++ bsd_x86_64_set_idt_base(env->idt.base);
++ bsd_x86_64_set_idt(0, 0);
++ bsd_x86_64_set_idt(1, 0);
++ bsd_x86_64_set_idt(2, 0);
++ bsd_x86_64_set_idt(3, 3);
++ bsd_x86_64_set_idt(4, 3);
++ bsd_x86_64_set_idt(5, 0);
++ bsd_x86_64_set_idt(6, 0);
++ bsd_x86_64_set_idt(7, 0);
++ bsd_x86_64_set_idt(8, 0);
++ bsd_x86_64_set_idt(9, 0);
++ bsd_x86_64_set_idt(10, 0);
++ bsd_x86_64_set_idt(11, 0);
++ bsd_x86_64_set_idt(12, 0);
++ bsd_x86_64_set_idt(13, 0);
++ bsd_x86_64_set_idt(14, 0);
++ bsd_x86_64_set_idt(15, 0);
++ bsd_x86_64_set_idt(16, 0);
++ bsd_x86_64_set_idt(17, 0);
++ bsd_x86_64_set_idt(18, 0);
++ bsd_x86_64_set_idt(19, 0);
++ bsd_x86_64_set_idt(0x80, 3);
++
++ /* segment setup */
++ env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
++ PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
++ env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
++ gdt_table = g2h(env->gdt.base);
++
++ /* 64 bit code segment */
++ bsd_x86_64_write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
++ DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | DESC_L_MASK
++ | (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
++
++ bsd_x86_64_write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff,
++ DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
++ (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
++
++ cpu_x86_load_seg(env, R_CS, __USER_CS);
++ cpu_x86_load_seg(env, R_SS, __USER_DS);
++ cpu_x86_load_seg(env, R_DS, 0);
++ cpu_x86_load_seg(env, R_ES, 0);
++ cpu_x86_load_seg(env, R_FS, 0);
++ cpu_x86_load_seg(env, R_GS, 0);
++}
++
++static inline void target_cpu_loop(CPUX86State *env)
++{
++ int trapnr;
++ abi_ulong pc;
++ /* target_siginfo_t info; */
++
++ for (;;) {
++ trapnr = cpu_x86_exec(env);
++ switch (trapnr) {
++ case 0x80:
++ /* syscall from int $0x80 */
++ if (bsd_type == target_freebsd) {
++ abi_ulong params = (abi_ulong) env->regs[R_ESP] +
++ sizeof(int32_t);
++ int32_t syscall_nr = env->regs[R_EAX];
++ int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
++
++ if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
++ get_user_s32(syscall_nr, params);
++ params += sizeof(int32_t);
++ } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
++ get_user_s32(syscall_nr, params);
++ params += sizeof(int64_t);
++ }
++ get_user_s32(arg1, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg2, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg3, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg4, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg5, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg6, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg7, params);
++ params += sizeof(int32_t);
++ get_user_s32(arg8, params);
++ env->regs[R_EAX] = do_freebsd_syscall(env,
++ syscall_nr,
++ arg1,
++ arg2,
++ arg3,
++ arg4,
++ arg5,
++ arg6,
++ arg7,
++ arg8);
++ } else { /* if (bsd_type == target_openbsd) */
++ env->regs[R_EAX] = do_openbsd_syscall(env,
++ env->regs[R_EAX],
++ env->regs[R_EBX],
++ env->regs[R_ECX],
++ env->regs[R_EDX],
++ env->regs[R_ESI],
++ env->regs[R_EDI],
++ env->regs[R_EBP]);
++ }
++ if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
++ env->regs[R_EAX] = -env->regs[R_EAX];
++ env->eflags |= CC_C;
++ } else {
++ env->eflags &= ~CC_C;
++ }
++ break;
++
++ case EXCP_SYSCALL:
++ /* syscall from syscall instruction */
++ if (bsd_type == target_freebsd) {
++ env->regs[R_EAX] = do_freebsd_syscall(env,
++ env->regs[R_EAX],
++ env->regs[R_EDI],
++ env->regs[R_ESI],
++ env->regs[R_EDX],
++ env->regs[R_ECX],
++ env->regs[8],
++ env->regs[9], 0, 0);
++ } else { /* if (bsd_type == target_openbsd) */
++ env->regs[R_EAX] = do_openbsd_syscall(env,
++ env->regs[R_EAX],
++ env->regs[R_EDI],
++ env->regs[R_ESI],
++ env->regs[R_EDX],
++ env->regs[10],
++ env->regs[8],
++ env->regs[9]);
++ }
++ env->eip = env->exception_next_eip;
++ if (((abi_ulong)env->regs[R_EAX]) >= (abi_ulong)(-515)) {
++ env->regs[R_EAX] = -env->regs[R_EAX];
++ env->eflags |= CC_C;
++ } else {
++ env->eflags &= ~CC_C;
++ }
++ break;
++
++#if 0
++ case EXCP0B_NOSEG:
++ case EXCP0C_STACK:
++ info.si_signo = SIGBUS;
++ info.si_errno = 0;
++ info.si_code = TARGET_SI_KERNEL;
++ info._sifields._sigfault._addr = 0;
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP0D_GPF:
++ /* XXX: potential problem if ABI32 */
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ info.si_code = TARGET_SI_KERNEL;
++ info._sifields._sigfault._addr = 0;
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP0E_PAGE:
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ if (!(env->error_code & 1)) {
++ info.si_code = TARGET_SEGV_MAPERR;
++ } else {
++ info.si_code = TARGET_SEGV_ACCERR;
++ }
++ info._sifields._sigfault._addr = env->cr[2];
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP00_DIVZ:
++ /* division by zero */
++ info.si_signo = SIGFPE;
++ info.si_errno = 0;
++ info.si_code = TARGET_FPE_INTDIV;
++ info._sifields._sigfault._addr = env->eip;
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP01_DB:
++ case EXCP03_INT3:
++ info.si_signo = SIGTRAP;
++ info.si_errno = 0;
++ if (trapnr == EXCP01_DB) {
++ info.si_code = TARGET_TRAP_BRKPT;
++ info._sifields._sigfault._addr = env->eip;
++ } else {
++ info.si_code = TARGET_SI_KERNEL;
++ info._sifields._sigfault._addr = 0;
++ }
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP04_INTO:
++ case EXCP05_BOUND:
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ info.si_code = TARGET_SI_KERNEL;
++ info._sifields._sigfault._addr = 0;
++ queue_signal(env, info.si_signo, &info);
++ break;
++
++ case EXCP06_ILLOP:
++ info.si_signo = SIGILL;
++ info.si_errno = 0;
++ info.si_code = TARGET_ILL_ILLOPN;
++ info._sifields._sigfault._addr = env->eip;
++ queue_signal(env, info.si_signo, &info);
++ break;
++#endif
++ case EXCP_INTERRUPT:
++ /* just indicate that signals should be handled asap */
++ break;
++#if 0
++ case EXCP_DEBUG:
++ {
++ 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;
++#endif
++ default:
++ pc = env->segs[R_CS].base + env->eip;
++ fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - "
++ "aborting\n", (long)pc, trapnr);
++ abort();
++ }
++ process_pending_signals(env);
++ }
++}
++
++static inline void target_cpu_clone_regs(CPUX86State *env, target_ulong newsp)
++{
++ if (newsp)
++ env->regs[R_ESP] = newsp;
++ env->regs[R_EAX] = 0;
++}
++
++static inline void target_cpu_reset(CPUArchState *cpu)
++{
++ cpu_reset(ENV_GET_CPU(cpu));
++}
++
++#endif /* ! _TARGET_ARCH_CPU_H_ */
+diff --git a/bsd-user/x86_64/target_arch_elf.h b/bsd-user/x86_64/target_arch_elf.h
+new file mode 100644
+index 0000000..bc7c6a1
+--- /dev/null
++++ b/bsd-user/x86_64/target_arch_elf.h
+@@ -0,0 +1,55 @@
++/*
++ * x86_64 ELF definitions
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_ELF_H_
++#define _TARGET_ARCH_ELF_H_
++
++#define ELF_START_MMAP 0x2aaaaab000ULL
++#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
++
++#define ELF_CLASS ELFCLASS64
++#define ELF_DATA ELFDATA2LSB
++#define ELF_ARCH EM_X86_64
++
++#define USE_ELF_CORE_DUMP
++#define ELF_EXEC_PAGESIZE 4096
++
++/* XXX */
++#ifndef __FreeBSD__
++#define ELF_PLATFORM target_elf_get_platform()
++
++static const char *target_elf_get_platform(void)
++{
++ static char elf_platform[] = "i386";
++ int family = (thread_env->cpuid_version >> 8) & 0xff;
++ if (family > 6)
++ family = 6;
++ if (family >= 3)
++ elf_platform[1] = '0' + family;
++ return elf_platform;
++}
++
++#define ELF_HWCAP target_elf_get_hwcap()
++
++static uint32_t target_elf_get_hwcap(void)
++{
++ return thread_env->features[FEAT_1_EDX];
++}
++#endif /* ! __FreeBSD__ */
++
++#endif /* _TARGET_ARCH_ELF_H_ */
+diff --git a/bsd-user/x86_64/target_arch_signal.h b/bsd-user/x86_64/target_arch_signal.h
+new file mode 100644
+index 0000000..1998570
+--- /dev/null
++++ b/bsd-user/x86_64/target_arch_signal.h
+@@ -0,0 +1,94 @@
++/*
++ * x86_64 signal definitions
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_SIGNAL_H_
++#define _TARGET_ARCH_SIGNAL_H_
++
++#include "cpu.h"
++
++/* Size of the signal trampolin code placed on the stack. */
++/* #define TARGET_SZSIGCODE (0) */ /* XXX to be added */
++
++/* compare to x86/include/_limits.h */
++#define TARGET_MINSIGSTKSZ (512 * 4) /* min sig stack size */
++#define TARGET_SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended size */
++
++#define TARGET_MC_GET_CLEAR_RET 0x0001
++
++struct target_sigcontext {
++ /* to be added */
++};
++
++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 {
++ 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];
++};
++
++/*
++ * Compare to amd64/amd64/machdep.c sendsig()
++ * Assumes that target stack frame memory is locked.
++ */
++static inline abi_long set_sigtramp_args(CPUX86State *regs,
++ int sig, struct target_sigframe *frame, abi_ulong frame_addr,
++ struct target_sigaction *ka)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++/* Compare to amd64/amd64/machdep.c get_mcontext() */
++static inline abi_long get_mcontext(CPUX86State *regs,
++ target_mcontext_t *mcp, int flags)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++/* Compare to amd64/amd64/machdep.c set_mcontext() */
++static inline abi_long set_mcontext(CPUX86State *regs,
++ target_mcontext_t *mcp, int srflag)
++{
++ /* XXX */
++ return -TARGET_EOPNOTSUPP;
++}
++
++static inline abi_long get_ucontext_sigreturn(CPUX86State *regs,
++ abi_ulong target_sf, abi_ulong *target_uc)
++{
++ /* XXX */
++ *target_uc = 0;
++ return -TARGET_EOPNOTSUPP;
++}
++
++#endif /* !TARGET_ARCH_SIGNAL_H_ */
+diff --git a/bsd-user/x86_64/target_arch_sigtramp.h b/bsd-user/x86_64/target_arch_sigtramp.h
+new file mode 100644
+index 0000000..f0f36d1
+--- /dev/null
++++ b/bsd-user/x86_64/target_arch_sigtramp.h
+@@ -0,0 +1,11 @@
++
++#ifndef _TARGET_ARCH_SIGTRAMP_H_
++#define _TARGET_ARCH_SIGTRAMP_H_
++
++static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc,
++ unsigned sys_sigreturn)
++{
++
++ return -TARGET_EOPNOTSUPP;
++}
++#endif /* _TARGET_ARCH_SIGTRAMP_H_ */
+diff --git a/bsd-user/x86_64/target_arch_sysarch.h b/bsd-user/x86_64/target_arch_sysarch.h
+new file mode 100644
+index 0000000..6d09d50
+--- /dev/null
++++ b/bsd-user/x86_64/target_arch_sysarch.h
+@@ -0,0 +1,76 @@
++/*
++ * x86_64 sysarch() syscall emulation
++ *
++ *
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __ARCH_SYSARCH_H_
++#define __ARCH_SYSARCH_H_
++
++#include "syscall.h"
++
++static inline abi_long do_freebsd_arch_sysarch(CPUX86State *env, int op,
++ abi_ulong parms)
++{
++ abi_long ret = 0;
++ abi_ulong val;
++ int idx;
++
++ switch (op) {
++ case TARGET_FREEBSD_AMD64_SET_GSBASE:
++ case TARGET_FREEBSD_AMD64_SET_FSBASE:
++ if (op == TARGET_FREEBSD_AMD64_SET_GSBASE) {
++ idx = R_GS;
++ } else {
++ idx = R_FS;
++ }
++ if (get_user(val, parms, abi_ulong)) {
++ return -TARGET_EFAULT;
++ }
++ cpu_x86_load_seg(env, idx, 0);
++ env->segs[idx].base = val;
++ break;
++
++ case TARGET_FREEBSD_AMD64_GET_GSBASE:
++ case TARGET_FREEBSD_AMD64_GET_FSBASE:
++ if (op == TARGET_FREEBSD_AMD64_GET_GSBASE) {
++ idx = R_GS;
++ } else {
++ idx = R_FS;
++ }
++ val = env->segs[idx].base;
++ if (put_user(val, parms, abi_ulong)) {
++ return -TARGET_EFAULT;
++ }
++ break;
++
++ /* XXX handle the others... */
++ default:
++ ret = -TARGET_EINVAL;
++ break;
++ }
++ return ret;
++}
++
++static inline void do_freebsd_arch_print_sysarch(
++ const struct syscallname *name, abi_long arg1, abi_long arg2,
++ abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6)
++{
++
++ gemu_log("%s(%d, " TARGET_ABI_FMT_lx ", " TARGET_ABI_FMT_lx ", "
++ TARGET_ABI_FMT_lx ")", name->name, (int)arg1, arg2, arg3, arg4);
++}
++
++#endif /*! __ARCH_SYSARCH_H_ */
+diff --git a/bsd-user/x86_64/target_arch_thread.h b/bsd-user/x86_64/target_arch_thread.h
+new file mode 100644
+index 0000000..d105e43
+--- /dev/null
++++ b/bsd-user/x86_64/target_arch_thread.h
+@@ -0,0 +1,40 @@
++/*
++ * x86_64 thread support
++ *
++ * Copyright (c) 2013 Stacey D. 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, see <http://www.gnu.org/licenses/>.
++ */
++#ifndef _TARGET_ARCH_THREAD_H_
++#define _TARGET_ARCH_THREAD_H_
++
++/* Compare to vm_machdep.c cpu_set_upcall_kse() */
++static inline void target_thread_set_upcall(CPUX86State *regs, abi_ulong entry,
++ abi_ulong arg, abi_ulong stack_base, abi_ulong stack_size)
++{
++ /* XXX */
++}
++
++static inline void target_thread_init(struct target_pt_regs *regs,
++ struct image_info *infop)
++{
++ regs->rax = 0;
++ regs->rsp = infop->start_stack;
++ regs->rip = infop->entry;
++ if (bsd_type == target_freebsd) {
++ regs->rdi = infop->start_stack;
++ }
++}
++
++#endif /* !_TARGET_ARCH_THREAD_H_ */
+diff --git a/bsd-user/x86_64/target_arch_vmparam.h b/bsd-user/x86_64/target_arch_vmparam.h
+new file mode 100644
+index 0000000..5e13076
+--- /dev/null
++++ b/bsd-user/x86_64/target_arch_vmparam.h
+@@ -0,0 +1,28 @@
++#ifndef _TARGET_ARCH_VMPARAM_H_
++#define _TARGET_ARCH_VMPARAM_H_
++
++#include "cpu.h"
++
++/* compare to amd64/include/vmparam.h */
++#define TARGET_MAXTSIZ (128UL*1024*1024) /* max text size */
++#define TARGET_DFLDSIZ (32768UL*1024*1024) /* initial data size limit */
++#define TARGET_MAXDSIZ (32768UL*1024*1024) /* max data size */
++#define TARGET_DFLSSIZ (8UL*1024*1024) /* initial stack size limit */
++#define TARGET_MAXSSIZ (512UL*1024*1024) /* max stack size */
++#define TARGET_SGROWSIZ (128UL*1024) /* amount to grow stack */
++
++#define TARGET_VM_MAXUSER_ADDRESS (0x0000800000000000UL)
++
++#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE)
++
++static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
++{
++ return state->regs[R_ESP];
++}
++
++static inline void set_second_rval(CPUX86State *state, abi_ulong retval2)
++{
++ state->regs[R_EDX] = retval2;
++}
++
++#endif /* !_TARGET_ARCH_VMPARAM_H_ */
+diff --git a/bsd-user/x86_64/target_signal.h b/bsd-user/x86_64/target_signal.h
+index 659cd40..5491687 100644
+--- a/bsd-user/x86_64/target_signal.h
++++ b/bsd-user/x86_64/target_signal.h
+@@ -11,9 +11,4 @@ typedef struct target_sigaltstack {
+ abi_ulong ss_size;
+ } target_stack_t;
+
+-static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+-{
+- return state->regs[R_ESP];
+-}
+-
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/configure b/configure
+index aae617e..f0b4da7 100755
+--- a/configure
++++ b/configure
+@@ -526,6 +526,9 @@ fi
+
+ # OS specific
+
++# host *BSD for user mode
++HOST_VARIANT_DIR=""
++
+ case $targetos in
+ CYGWIN*)
+ mingw32="yes"
+@@ -551,12 +554,14 @@ FreeBSD)
+ # needed for kinfo_getvmmap(3) in libutil.h
+ LIBS="-lutil $LIBS"
+ netmap="" # enable netmap autodetect
++ HOST_VARIANT_DIR="freebsd"
+ ;;
+ DragonFly)
+ bsd="yes"
+ make="${MAKE-gmake}"
+ audio_drv_list="oss"
+ audio_possible_drivers="oss sdl esd pa"
++ HOST_VARIANT_DIR="dragonfly"
+ ;;
+ NetBSD)
+ bsd="yes"
+@@ -564,12 +569,14 @@ NetBSD)
+ audio_drv_list="oss"
+ audio_possible_drivers="oss sdl esd"
+ oss_lib="-lossaudio"
++ HOST_VARIANT_DIR="netbsd"
+ ;;
+ OpenBSD)
+ bsd="yes"
+ make="${MAKE-gmake}"
+ audio_drv_list="sdl"
+ audio_possible_drivers="sdl esd"
++ HOST_VARIANT_DIR="openbsd"
+ ;;
+ Darwin)
+ bsd="yes"
+@@ -587,6 +594,7 @@ Darwin)
+ # Disable attempts to use ObjectiveC features in os/object.h since they
+ # won't work when we're compiling with gcc as a C compiler.
+ QEMU_CFLAGS="-DOS_OBJECT_USE_OBJC=0 $QEMU_CFLAGS"
++ HOST_VARIANT_DIR="darwin"
+ ;;
+ SunOS)
+ solaris="yes"
+@@ -4894,6 +4902,9 @@ if [ "$TARGET_ABI_DIR" = "" ]; then
+ TARGET_ABI_DIR=$TARGET_ARCH
+ fi
+ echo "TARGET_ABI_DIR=$TARGET_ABI_DIR" >> $config_target_mak
++if [ "$HOST_VARIANT_DIR" != "" ]; then
++ echo "HOST_VARIANT_DIR=$HOST_VARIANT_DIR" >> $config_target_mak
++fi
+ case "$target_name" in
+ i386|x86_64)
+ if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
+diff --git a/default-configs/arm-bsd-user.mak b/default-configs/arm-bsd-user.mak
+new file mode 100644
+index 0000000..869e6fb
+--- /dev/null
++++ b/default-configs/arm-bsd-user.mak
+@@ -0,0 +1,3 @@
++# Default configuration for arm-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/mips64el-bsd-user.mak b/default-configs/mips64el-bsd-user.mak
+new file mode 100644
+index 0000000..b879228
+--- /dev/null
++++ b/default-configs/mips64el-bsd-user.mak
+@@ -0,0 +1 @@
++# Default configuration for mips64el-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/include/qemu/aes.h b/include/qemu/aes.h
+index e79c707..6d253a3 100644
+--- a/include/qemu/aes.h
++++ b/include/qemu/aes.h
+@@ -10,6 +10,15 @@ struct aes_key_st {
+ };
+ typedef struct aes_key_st AES_KEY;
+
++/* FreeBSD has it's own AES_set_decrypt_key in -lcrypto, avoid conflicts. */
++#ifdef __FreeBSD__
++#define AES_set_encrypt_key QEMU_AES_set_encrypt_key
++#define AES_set_decrypt_key QEMU_AES_set_decrypt_key
++#define AES_encrypt QEMU_AES_encrypt
++#define AES_decrypt QEMU_AES_decrypt
++#define AES_cbc_encrypt QEMU_AES_cbc_encrypt
++#endif
++
+ int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
+ AES_KEY *key);
+ int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+diff --git a/include/qemu/tls.h b/include/qemu/tls.h
+index b92ea9d..ae7d79d 100644
+--- a/include/qemu/tls.h
++++ b/include/qemu/tls.h
+@@ -38,7 +38,7 @@
+ * TODO: proper implementations via Win32 .tls sections and
+ * POSIX pthread_getspecific.
+ */
+-#ifdef __linux__
++#if defined(__linux__) || defined(__FreeBSD__)
+ #define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x)
+ #define DEFINE_TLS(type, x) __thread __typeof__(type) tls__##x
+ #define tls_var(x) tls__##x
diff --git a/emulators/qemu-devel/files/extra-patch-9ac2c49c734a49025fe1647ce84728d3988ea5d2 b/emulators/qemu-devel/files/extra-patch-9ac2c49c734a49025fe1647ce84728d3988ea5d2
new file mode 100644
index 000000000000..048a3ede5414
--- /dev/null
+++ b/emulators/qemu-devel/files/extra-patch-9ac2c49c734a49025fe1647ce84728d3988ea5d2
@@ -0,0 +1,14 @@
+diff --git a/bsd-user/freebsd/os-sys.c b/bsd-user/freebsd/os-sys.c
+index c8f999f..2578645 100644
+--- a/bsd-user/freebsd/os-sys.c
++++ b/bsd-user/freebsd/os-sys.c
+@@ -130,7 +130,8 @@ abi_long do_freebsd_sysctl(CPUArchState *env, abi_ulong namep, int32_t namelen,
+ abi_ulong oldlen = 0;
+ int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i;
+ uint32_t kind = 0;
+- TaskState *ts = (TaskState *)env->opaque;
++ CPUState *cpu = ENV_GET_CPU(env);
++ TaskState *ts = cpu->opaque;
+
+ if (oldlenp) {
+ if (get_user_ual(oldlen, oldlenp)) {
diff --git a/emulators/qemu-devel/files/extra-patch-a3129eea10f188bfd39ce83b18b25dcefbc5bffc b/emulators/qemu-devel/files/extra-patch-a3129eea10f188bfd39ce83b18b25dcefbc5bffc
new file mode 100644
index 000000000000..11056d010961
--- /dev/null
+++ b/emulators/qemu-devel/files/extra-patch-a3129eea10f188bfd39ce83b18b25dcefbc5bffc
@@ -0,0 +1,53 @@
+diff --git a/bsd-user/signal.c b/bsd-user/signal.c
+index 3619b00..01374a6 100644
+--- a/bsd-user/signal.c
++++ b/bsd-user/signal.c
+@@ -283,7 +283,8 @@ static int core_dump_signal(int sig)
+ /* Signal queue handling. */
+ static inline struct qemu_sigqueue *alloc_sigqueue(CPUArchState *env)
+ {
+- TaskState *ts = env->opaque;
++ CPUState *cpu = thread_cpu;
++ TaskState *ts = (TaskState *)cpu->opaque;
+ struct qemu_sigqueue *q = ts->first_free;
+
+ if (!q) {
+@@ -296,7 +297,8 @@ static inline struct qemu_sigqueue *alloc_sigqueue(CPUArchState *env)
+ static inline void free_sigqueue(CPUArchState *env, struct qemu_sigqueue *q)
+ {
+
+- TaskState *ts = env->opaque;
++ CPUState *cpu = thread_cpu;
++ TaskState *ts = (TaskState *)cpu->opaque;
+ q->next = ts->first_free;
+ ts->first_free = q;
+ }
+@@ -305,7 +307,8 @@ static inline void free_sigqueue(CPUArchState *env, struct qemu_sigqueue *q)
+ void QEMU_NORETURN force_sig(int target_sig)
+ {
+ CPUArchState *env = thread_cpu->env_ptr;
+- TaskState *ts = (TaskState *)env->opaque;
++ CPUState *cpu = thread_cpu;
++ TaskState *ts = (TaskState *)cpu->opaque;
+ int core_dumped = 0;
+ int host_sig;
+ struct sigaction act;
+@@ -365,7 +368,8 @@ void QEMU_NORETURN force_sig(int target_sig)
+ */
+ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info)
+ {
+- TaskState *ts = env->opaque;
++ CPUState *cpu = thread_cpu;
++ TaskState *ts = (TaskState *)cpu->opaque;
+ struct emulated_sigtable *k;
+ struct qemu_sigqueue *q, **pq;
+ abi_ulong handler;
+@@ -826,7 +830,7 @@ void process_pending_signals(CPUArchState *cpu_env)
+ struct emulated_sigtable *k;
+ struct target_sigaction *sa;
+ struct qemu_sigqueue *q;
+- TaskState *ts = cpu_env->opaque;
++ TaskState *ts = cpu->opaque;
+
+ if (!ts->signal_pending) {
+ return;
diff --git a/emulators/qemu-devel/files/extra-patch-bsd-user-freebsd-os-proc.c b/emulators/qemu-devel/files/extra-patch-bsd-user-freebsd-os-proc.c
index 78c80e43a3a1..b53b82e72d69 100644
--- a/emulators/qemu-devel/files/extra-patch-bsd-user-freebsd-os-proc.c
+++ b/emulators/qemu-devel/files/extra-patch-bsd-user-freebsd-os-proc.c
@@ -1,3 +1,14 @@
+From nox Mon Sep 17 00:00:00 2001
+From: Juergen Lock <nox@jelal.kn-bremen.de>
+Date: 22 Mar 2014 00:21:00 +0100
+Subject: Fix bsd-user targets running scripts with shebang args
+
+This fixes running scripts starting like:
+
+ #! /usr/bin/perl -w
+
+Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>
+
--- a/bsd-user/freebsd/os-proc.c
--- b/bsd-user/freebsd/os-proc.c
@@ -83,7 +83,7 @@ out:
diff --git a/emulators/qemu-devel/files/extra-patch-bsd-user-mips-target_arch_vmparam.h b/emulators/qemu-devel/files/extra-patch-bsd-user-mips-target_arch_vmparam.h
index f022cbb696c2..ec347bbb8d6f 100644
--- a/emulators/qemu-devel/files/extra-patch-bsd-user-mips-target_arch_vmparam.h
+++ b/emulators/qemu-devel/files/extra-patch-bsd-user-mips-target_arch_vmparam.h
@@ -1,3 +1,13 @@
+From nox Mon Sep 17 00:00:00 2001
+From: Juergen Lock <nox@jelal.kn-bremen.de>
+Date: 04 Apr 2014 02:09:00 +0200
+Subject: Lower 32bit mips TARGET_USRSTACK
+
+Lower 32bit mips TARGET_USRSTACK to fix an assert starting mips-bsd-user
+processes on 64bit hosts. (like amd64)
+
+Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>
+
--- a/bsd-user/mips/target_arch_vmparam.h
+++ b/bsd-user/mips/target_arch_vmparam.h
@@ -35,7 +35,8 @@
diff --git a/emulators/qemu-devel/files/extra-patch-bsd-user-mmap.c b/emulators/qemu-devel/files/extra-patch-bsd-user-mmap.c
index 9370e5bd7fd3..f8b393397839 100644
--- a/emulators/qemu-devel/files/extra-patch-bsd-user-mmap.c
+++ b/emulators/qemu-devel/files/extra-patch-bsd-user-mmap.c
@@ -1,3 +1,13 @@
+From nox Mon Sep 17 00:00:00 2001
+From: Juergen Lock <nox@jelal.kn-bremen.de>
+Date: 06 Apr 2014 02:20:00 +0200
+Subject: Wrap bsd-user mmap(2) allocation search to low memory
+
+Wrap bsd-user mmap(2) allocation search to low memory to avoid
+another assert on 64bit hosts.
+
+Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>
+
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -238,8 +238,13 @@ abi_ulong mmap_find_vma(abi_ulong start,
diff --git a/emulators/qemu-devel/files/extra-patch-bsd-user-syscall.c b/emulators/qemu-devel/files/extra-patch-bsd-user-syscall.c
index 3570ca234e35..1dda197e9c3d 100644
--- a/emulators/qemu-devel/files/extra-patch-bsd-user-syscall.c
+++ b/emulators/qemu-devel/files/extra-patch-bsd-user-syscall.c
@@ -1,3 +1,12 @@
+From nox Mon Sep 17 00:00:00 2001
+From: Juergen Lock <nox@jelal.kn-bremen.de>
+Date: 05 Apr 2014 02:04:00 +0200
+Subject: Fix bsd-user FreeBSD fchflags() syscall (typo)
+
+Fix bsd-user FreeBSD fchflags() syscall. (typo)
+
+Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>
+
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -627,7 +627,7 @@ abi_long do_freebsd_syscall(void *cpu_en
diff --git a/emulators/qemu-devel/files/extra-patch-c13_tls2 b/emulators/qemu-devel/files/extra-patch-c13_tls2
new file mode 100644
index 000000000000..fca58f546c57
--- /dev/null
+++ b/emulators/qemu-devel/files/extra-patch-c13_tls2
@@ -0,0 +1,15 @@
+--- a/bsd-user/arm/target_arch_cpu.c
++++ b/bsd-user/arm/target_arch_cpu.c
+@@ -18,10 +18,10 @@
+
+ void target_cpu_set_tls(CPUARMState *env, target_ulong newtls)
+ {
+- env->cp15.c13_tls2 = newtls;
++ env->cp15.tpidrro_el0 = newtls;
+ }
+
+ target_ulong target_cpu_get_tls(CPUARMState *env)
+ {
+- return (env->cp15.c13_tls2);
++ return (env->cp15.tpidrro_el0);
+ }
diff --git a/emulators/qemu-devel/files/extra-patch-fd7ec8e06cd1876ef478975f052ff64134d19c6c b/emulators/qemu-devel/files/extra-patch-fd7ec8e06cd1876ef478975f052ff64134d19c6c
new file mode 100644
index 000000000000..27bc834a9844
--- /dev/null
+++ b/emulators/qemu-devel/files/extra-patch-fd7ec8e06cd1876ef478975f052ff64134d19c6c
@@ -0,0 +1,13 @@
+diff --git a/bsd-user/freebsd/os-thread.h b/bsd-user/freebsd/os-thread.h
+index 5e24852..28f737f 100644
+--- a/bsd-user/freebsd/os-thread.h
++++ b/bsd-user/freebsd/os-thread.h
+@@ -68,7 +68,7 @@ static abi_long do_freebsd_thr_exit(CPUArchState *cpu_env, abi_ulong tid_addr)
+ }
+ thread_cpu = NULL;
+ object_unref(OBJECT(ENV_GET_CPU(cpu_env)));
+- ts = ((CPUArchState *)cpu_env)->opaque;
++ ts = cpu->opaque;
+ g_free(ts);
+ pthread_exit(NULL);
+ /* Doesn't return */
diff --git a/emulators/qemu-devel/files/extra-patch-inherit-interp_prefix b/emulators/qemu-devel/files/extra-patch-inherit-interp_prefix
index 6cfb157353a1..3d1c360b8e07 100644
--- a/emulators/qemu-devel/files/extra-patch-inherit-interp_prefix
+++ b/emulators/qemu-devel/files/extra-patch-inherit-interp_prefix
@@ -1,3 +1,13 @@
+From nox Mon Sep 17 00:00:00 2001
+From: Juergen Lock <nox@jelal.kn-bremen.de>
+Date: 04 Apr 2014 16:36:00 +0200
+Subject: Pass down interp_prefix (-L arg) to bsd-user child processes
+
+Pass down interp_prefix (-L arg) to bsd-user target child processes
+so running shared target binaries as subprocesses works.
+
+Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>
+
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -58,7 +58,7 @@ unsigned long reserved_va;
diff --git a/emulators/qemu-devel/files/extra-patch-sysctl-0oldlen b/emulators/qemu-devel/files/extra-patch-sysctl-0oldlen
index 72a8d52d92d7..0f2d96e5ee1d 100644
--- a/emulators/qemu-devel/files/extra-patch-sysctl-0oldlen
+++ b/emulators/qemu-devel/files/extra-patch-sysctl-0oldlen
@@ -1,3 +1,13 @@
+From nox Mon Sep 17 00:00:00 2001
+From: Juergen Lock <nox@jelal.kn-bremen.de>
+Date: 05 Apr 2014 23:36:00 +0200
+Subject: Fix FreeBSD sysctls kern.usrstack and kern.ps_strings
+
+Fix FreeBSD sysctls kern.usrstack and kern.ps_strings invoked with
+oidlen zero. (like from sysctl(8))
+
+Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>
+
--- a/bsd-user/freebsd/os-sys.c
+++ b/bsd-user/freebsd/os-sys.c
@@ -165,7 +165,9 @@ abi_long do_freebsd_sysctl(CPUArchState
diff --git a/emulators/qemu-devel/files/extra-patch-sysctl-hw-availpages b/emulators/qemu-devel/files/extra-patch-sysctl-hw-availpages
index 914f146961b4..5253802430bc 100644
--- a/emulators/qemu-devel/files/extra-patch-sysctl-hw-availpages
+++ b/emulators/qemu-devel/files/extra-patch-sysctl-hw-availpages
@@ -1,3 +1,13 @@
+From nox Mon Sep 17 00:00:00 2001
+From: Juergen Lock <nox@jelal.kn-bremen.de>
+Date: 05 Apr 2014 21:06:00 +0200
+Subject: Fix bsd-user FreeBSD hw.availpages sysctl
+
+hw.availpages is defined as OID_AUTO so the mib can change; find out
+it's value at the first hw.* sysctl syscall.
+
+Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>
+
--- a/bsd-user/freebsd/os-sys.c
+++ b/bsd-user/freebsd/os-sys.c
@@ -219,24 +219,36 @@ abi_long do_freebsd_sysctl(CPUArchState
diff --git a/emulators/qemu-devel/files/patch-configure b/emulators/qemu-devel/files/patch-configure
index 49b7e000a62d..e87341476e6b 100644
--- a/emulators/qemu-devel/files/patch-configure
+++ b/emulators/qemu-devel/files/patch-configure
@@ -9,16 +9,16 @@
datadir="\${prefix}/share"
qemu_docdir="\${prefix}/share/doc/qemu"
bindir="\${prefix}/bin"
-@@ -1749,7 +1749,7 @@ if test "$gtk" != "no"; then
- gtk_libs=`$pkg_config --libs $gtkpackage`
- vte_cflags=`$pkg_config --cflags $vtepackage`
- vte_libs=`$pkg_config --libs $vtepackage`
-- libs_softmmu="$gtk_libs $vte_libs $libs_softmmu"
-+ libs_softmmu="$gtk_libs -lintl $vte_libs $libs_softmmu"
- gtk="yes"
- fi
- fi
-@@ -2956,15 +2956,18 @@ if compile_prog "" "" ; then
+@@ -1980,7 +1980,7 @@ if test "$gtk" != "no"; then
+ if $pkg_config --exists "$gtkpackage >= $gtkversion"; then
+ gtk_cflags=`$pkg_config --cflags $gtkpackage`
+ gtk_libs=`$pkg_config --libs $gtkpackage`
+- libs_softmmu="$gtk_libs $libs_softmmu"
++ libs_softmmu="$gtk_libs -lintl $libs_softmmu"
+ gtk="yes"
+ elif test "$gtk" = "yes"; then
+ feature_not_found "gtk" "Install gtk2 or gtk3 (requires --with-gtkabi=3.0 option to configure) devel"
+@@ -3320,15 +3320,18 @@ if compile_prog "" "" ; then
fi
# Check if tools are available to build documentation.
@@ -27,7 +27,7 @@
+# docs=yes
+# else
+# if test "$docs" = "yes" ; then
-+# feature_not_found "docs"
++# feature_not_found "docs" "Install texinfo and Perl/perl-podlators"
+# fi
+# docs=no
+# fi
@@ -37,7 +37,7 @@
- docs=yes
- else
- if test "$docs" = "yes" ; then
-- feature_not_found "docs"
+- feature_not_found "docs" "Install texinfo and Perl/perl-podlators"
- fi
- docs=no
- fi
@@ -45,15 +45,10 @@
fi
# Search for bswap_32 function
-@@ -3121,17 +3124,30 @@ fi
+@@ -3498,6 +3501,17 @@ fi
# check for libusb
if test "$libusb" != "no" ; then
-- if $pkg_config --atleast-version=1.0.13 libusb-1.0; then
-- libusb="yes"
-- libusb_cflags=$($pkg_config --cflags libusb-1.0)
-- libusb_libs=$($pkg_config --libs libusb-1.0)
-- QEMU_CFLAGS="$QEMU_CFLAGS $libusb_cflags"
+ cat > $TMPC << EOF
+#include <libusb.h>
+
@@ -63,24 +58,16 @@
+ libusb="yes"
+ libusb_cflags=""
+ libusb_libs=-lusb
- libs_softmmu="$libs_softmmu $libusb_libs"
- else
-- if test "$libusb" = "yes"; then
-- feature_not_found "libusb"
-+ if $pkg_config --atleast-version=1.0.13 libusb-1.0; then
-+ libusb="yes"
-+ usb="libusb"
-+ libusb_cflags=$($pkg_config --cflags libusb-1.0)
-+ libusb_libs=$($pkg_config --libs libusb-1.0)
-+ QEMU_CFLAGS="$QEMU_CFLAGS $libusb_cflags"
-+ libs_softmmu="$libs_softmmu $libusb_libs"
-+ else
-+ if test "$libusb" = "yes"; then
-+ feature_not_found "libusb"
-+ fi
-+ libusb="no"
++ libs_softmmu="$libs_softmmu $libusb_libs"
++ else
+ if $pkg_config --atleast-version=1.0.13 libusb-1.0; then
+ libusb="yes"
+ libusb_cflags=$($pkg_config --cflags libusb-1.0)
+@@ -3510,6 +3524,7 @@ if test "$libusb" != "no" ; then
fi
-- libusb="no"
+ libusb="no"
fi
++ fi
fi
+ # check for usbredirparser for usb network redirection support
diff --git a/emulators/qemu-devel/files/patch-tcg-i386-tcg-target.c b/emulators/qemu-devel/files/patch-tcg-i386-tcg-target.c
deleted file mode 100644
index 308f934b4965..000000000000
--- a/emulators/qemu-devel/files/patch-tcg-i386-tcg-target.c
+++ /dev/null
@@ -1,13 +0,0 @@
---- a/tcg/i386/tcg-target.c
-+++ b/tcg/i386/tcg-target.c
-@@ -104,6 +104,10 @@ static const int tcg_target_call_oarg_re
- # define have_cmov 1
- #elif defined(CONFIG_CPUID_H)
- #include <cpuid.h>
-+#ifndef bit_CMOV
-+/* clang's <cpuid.h> doesn't define bit_* */
-+#define bit_CMOV (1 << 15)
-+#endif
- static bool have_cmov;
- #else
- # define have_cmov 0
diff --git a/emulators/qemu-devel/files/pcap-patch b/emulators/qemu-devel/files/pcap-patch
index 1688360e8c6c..497827e6037c 100644
--- a/emulators/qemu-devel/files/pcap-patch
+++ b/emulators/qemu-devel/files/pcap-patch
@@ -1,16 +1,16 @@
--- configure.orig
+++ configure
-@@ -261,6 +261,9 @@ gtkabi="2.0"
- tpm="no"
+@@ -324,6 +324,9 @@ tpm="no"
libssh2=""
vhdx=""
+ quorum="no"
+pcap="no"
+pcap_create="no"
+bpf="no"
# parse CC options first
for opt do
-@@ -787,6 +790,10 @@ for opt do
+@@ -865,6 +868,10 @@ for opt do
;;
--enable-vnc-ws) vnc_ws="yes"
;;
@@ -21,7 +21,7 @@
--disable-slirp) slirp="no"
;;
--disable-uuid) uuid="no"
-@@ -1884,6 +1891,51 @@ EOF
+@@ -2130,6 +2137,51 @@ EOF
fi
##########################################
@@ -73,7 +73,7 @@
# VNC TLS/WS detection
if test "$vnc" = "yes" -a \( "$vnc_tls" != "no" -o "$vnc_ws" != "no" \) ; then
cat > $TMPC <<EOF
-@@ -3747,6 +3799,7 @@ echo "Audio drivers $audio_drv_list"
+@@ -4133,6 +4185,7 @@ echo "Audio drivers $audio_drv_list"
echo "Block whitelist (rw) $block_drv_rw_whitelist"
echo "Block whitelist (ro) $block_drv_ro_whitelist"
echo "VirtFS support $virtfs"
@@ -81,7 +81,7 @@
echo "VNC support $vnc"
if test "$vnc" = "yes" ; then
echo "VNC TLS support $vnc_tls"
-@@ -3897,6 +3950,15 @@ fi
+@@ -4297,6 +4350,15 @@ fi
if test "$profiler" = "yes" ; then
echo "CONFIG_PROFILER=y" >> $config_host_mak
fi
diff --git a/emulators/qemu-devel/files/prepatch-configure b/emulators/qemu-devel/files/prepatch-configure
deleted file mode 100644
index 1b4708fc382f..000000000000
--- a/emulators/qemu-devel/files/prepatch-configure
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/configure
-+++ b/configure
-@@ -491,6 +491,7 @@ FreeBSD)
- audio_possible_drivers="oss sdl esd pa"
- # needed for kinfo_getvmmap(3) in libutil.h
- LIBS="-lutil $LIBS"
-+ netmap="" # enable netmap autodetect
- ;;
- DragonFly)
- bsd="yes"