aboutsummaryrefslogtreecommitdiffstats
path: root/emulators
diff options
context:
space:
mode:
authornox <nox@FreeBSD.org>2013-04-26 03:34:20 +0800
committernox <nox@FreeBSD.org>2013-04-26 03:34:20 +0800
commit7424ce8f133aa8be79f834eb7745add6819988ac (patch)
treeba21ba1f6d2c2ec4ce4421f6624a2352c13284eb /emulators
parentc81b92899d4198fda559e76561884ffed5c11eeb (diff)
downloadfreebsd-ports-gnome-7424ce8f133aa8be79f834eb7745add6819988ac.tar.gz
freebsd-ports-gnome-7424ce8f133aa8be79f834eb7745add6819988ac.tar.zst
freebsd-ports-gnome-7424ce8f133aa8be79f834eb7745add6819988ac.zip
- Update to sson's latest bsd-user patches.
- Turns out qemu 1.4.x now builds with clang (almost) as is, so remove CLANG_HACK. [1] - Add workaround for clang/i386 that doesn't define bit_CMOV in <cpuid.h>. Submitted by: Brad Smith <brad@comstyle.com> [1]
Diffstat (limited to 'emulators')
-rw-r--r--emulators/qemu-devel/Makefile17
-rw-r--r--emulators/qemu-devel/files/patch-tcg-i386-tcg-target.c13
-rw-r--r--emulators/qemu-devel/files/patch-za-bsd-user-8fix28
-rw-r--r--emulators/qemu-devel/files/patch-zb2-bsd-user-sson004b1048
4 files changed, 1069 insertions, 37 deletions
diff --git a/emulators/qemu-devel/Makefile b/emulators/qemu-devel/Makefile
index dbc94d0aa26e..bb40de285037 100644
--- a/emulators/qemu-devel/Makefile
+++ b/emulators/qemu-devel/Makefile
@@ -3,6 +3,7 @@
PORTNAME= qemu
PORTVERSION= 1.4.0
+PORTREVISION= 1
CATEGORIES= emulators
MASTER_SITES= http://wiki.qemu.org/download/:release \
LOCAL/nox:snapshot
@@ -31,7 +32,7 @@ CONFLICTS_INSTALL= qemu-[0-9]*
MAKE_JOBS_SAFE= yes
OPTIONS_DEFINE= SAMBA SDL OPENGL GNUTLS SASL JPEG PNG CDROM_DMA PCAP \
- USBREDIR GNS3 ADD_AUDIO CLANG_HACK X86_TARGETS BSD_USER \
+ USBREDIR GNS3 ADD_AUDIO X86_TARGETS BSD_USER \
STATIC_LINK DOCS
SAMBA_DESC= samba dependency (for -smb)
GNUTLS_DESC= gnutls dependency (vnc encryption)
@@ -44,7 +45,6 @@ SEABIOS_GIT_DESC= add seabios snapshot (-bios bios.bin-1.6.3.1)
USBREDIR_DESC= usb device network redirection (experimental!)
GNS3_DESC= gns3 patches (promiscuous multicast)
ADD_AUDIO_DESC= Emulate more audio hardware (experimental!)
-CLANG_HACK_DESC= clang workaround (result slow and less stable!)
X86_TARGETS_DESC= Don't build non-x86 system targets
BSD_USER_DESC= Also build bsd-user targets (for testing)
STATIC_LINK_DESC= Statically link the executables
@@ -55,16 +55,6 @@ OPTIONS_DEFAULT=SDL OPENGL GNUTLS SASL JPEG PNG CDROM_DMA PCAP
CONFIGURE_ARGS+= --extra-ldflags=-L${LOCALBASE}/lib
PORTDOCS= docs qemu-doc.html qemu-tech.html qmp-commands.txt
-# XXX this fixes build with clang but --enable-tcg-interpreter that's
-# needed to avoid global register usage that clang doesn't support
-# causes the result to be slow and less stable.
-.if ${PORT_OPTIONS:MCLANG_HACK}
-CONFIGURE_ARGS+= --enable-tcg-interpreter
-CLANG_CFLAGS_AS+= -no-integrated-as
-.else
-USE_GCC= any
-.endif
-
.if ${PORT_OPTIONS:MX86_TARGETS}
.if ${PORT_OPTIONS:MBSD_USER}
.if ${ARCH} != "amd64"
@@ -230,9 +220,6 @@ post-patch:
-e "s|^(LDFLAGS=).*|\1${LDFLAGS}|" \
${WRKSRC}/Makefile
@${REINPLACE_CMD} -E \
- -e "s|^(CFLAGS[ ]*:=.*)|\1 ${CLANG_CFLAGS_AS}|" \
- ${WRKSRC}/pc-bios/optionrom/Makefile
- @${REINPLACE_CMD} -E \
-e "1s|^(#! )/usr/bin/perl|\1${PERL}|" \
${WRKSRC}/scripts/texi2pod.pl
diff --git a/emulators/qemu-devel/files/patch-tcg-i386-tcg-target.c b/emulators/qemu-devel/files/patch-tcg-i386-tcg-target.c
new file mode 100644
index 000000000000..308f934b4965
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-tcg-i386-tcg-target.c
@@ -0,0 +1,13 @@
+--- 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/patch-za-bsd-user-8fix b/emulators/qemu-devel/files/patch-za-bsd-user-8fix
index ef409469c549..a8653c16722d 100644
--- a/emulators/qemu-devel/files/patch-za-bsd-user-8fix
+++ b/emulators/qemu-devel/files/patch-za-bsd-user-8fix
@@ -1,28 +1,12 @@
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
-@@ -123,6 +123,7 @@ get_filename_from_fd(pid_t pid, int fd,
- struct filestat *fst;
- char *ret = NULL;
-
+@@ -106,7 +106,9 @@ static char *get_filename_from_fd(pid_t
+ #ifdef __FreeBSD__
+ #include <sys/queue.h>
+ #include <sys/user.h>
+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
- procstat = procstat_open_sysctl();
- if (NULL == procstat)
- goto out;
-@@ -152,6 +153,7 @@ out:
- procstat_freeprocs(procstat, kipp);
- if (procstat != NULL)
- procstat_close(procstat);
+ #include <libprocstat.h>
+#endif
- return (ret);
- }
-@@ -1739,7 +1741,9 @@ int_case:
- case IP_RECVDSTADDR:
- case IP_RETOPTS:
-+#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
- case IP_RECVTOS:
-+#endif
- case IP_MULTICAST_TTL:
- case IP_MULTICAST_LOOP:
- case IP_PORTRANGE:
+ /*
diff --git a/emulators/qemu-devel/files/patch-zb2-bsd-user-sson004b b/emulators/qemu-devel/files/patch-zb2-bsd-user-sson004b
new file mode 100644
index 000000000000..fc772caf9c31
--- /dev/null
+++ b/emulators/qemu-devel/files/patch-zb2-bsd-user-sson004b
@@ -0,0 +1,1048 @@
+diff --git a/bsd-user/arm/target_signal.h b/bsd-user/arm/target_signal.h
+index 05c9d1c..214d691 100644
+--- a/bsd-user/arm/target_signal.h
++++ b/bsd-user/arm/target_signal.h
+@@ -67,6 +67,29 @@ struct target_sigframe {
+ target_ucontext_t sf_uc; /* saved ucontext */
+ };
+
++/* compare to sys/arm/include/frame.h */
++typedef 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;
++} target_trapframe_t;
++
+ #define TARGET_SZSIGCODE (8 * 4)
+
+ /* Compare to arm/arm/locore.S ENTRY_NP(sigcode) */
+@@ -224,4 +247,22 @@ get_ucontext_sigreturn(CPUARMState *regs, abi_ulong sf_addr,
+ return (0);
+ }
+
++/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */
++/* XXX crashes on first shared lib call */
++static inline void
++thread_set_upcall(CPUARMState *regs, abi_ulong entry, abi_ulong arg,
++ abi_ulong stack_base, abi_ulong stack_size)
++{
++ abi_ulong sp;
++
++ sp = ((stack_base + stack_size) & (8 - 1)) - sizeof(struct target_trapframe);
++
++ /* fp = sp = stack base */
++ regs->regs[11] = regs->regs[13] = sp;
++ /* pc = start function entry */
++ regs->regs[15] = regs->regs[14] = entry & 0xfffffffe;
++ /* r0 = arg */
++ regs->regs[0] = arg;
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/arm/target_vmparam.h b/bsd-user/arm/target_vmparam.h
+index bc50fbb..2186c68 100644
+--- a/bsd-user/arm/target_vmparam.h
++++ b/bsd-user/arm/target_vmparam.h
+@@ -1,7 +1,19 @@
+ #ifndef _TARGET_VMPARAM_H_
+ #define _TARGET_VMPARAM_H_
+
++#define TARGET_HW_MACHINE "arm"
++#define TARGET_HW_MACHINE_ARCH "armv6"
++
+ #if defined(__FreeBSD__)
++
++/* compare to 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 */
++
+ /* KERNBASE - 512 MB */
+ #define TARGET_VM_MAXUSER_ADDRESS (0xc0000000 - (512 * 1024 * 1024))
+ #define TARGET_USRSTACK TARGET_VM_MAXUSER_ADDRESS
+@@ -18,10 +30,6 @@ struct target_ps_strings {
+
+ #define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
+
+-/* Make stack size large enough to hold everything. */
+-#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
+- MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
+-
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
+index 7a7c3eb..da9ad73 100644
+--- a/bsd-user/elfload.c
++++ b/bsd-user/elfload.c
+@@ -701,13 +701,7 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm,
+ /* Create enough stack to hold everything. If we don't use
+ * it for args, we'll use it for something else...
+ */
+-#ifdef TARGET_STACK_SIZE
+- size = TARGET_STACK_SIZE;
+-#else
+- size = x86_stack_size;
+- if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
+- size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
+-#endif
++ size = target_dflssiz;
+
+ #ifdef TARGET_USRSTACK
+ stack_base = TARGET_USRSTACK - size;
+diff --git a/bsd-user/i386/target_signal.h b/bsd-user/i386/target_signal.h
+index 51a2a7b..034b455 100644
+--- a/bsd-user/i386/target_signal.h
++++ b/bsd-user/i386/target_signal.h
+@@ -45,4 +45,12 @@ get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
+ return (-TARGET_ENOSYS);
+ }
+
++/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */
++static inline void
++thread_set_upcall(CPUArchState *regs, abi_ulong entry, abi_ulong arg,
++ abi_ulong stack_base, abi_ulong stack_size)
++{
++ fprintf(stderr, "i386 doesn't have support for thread_set_upcall()\n");
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/i386/target_vmparam.h b/bsd-user/i386/target_vmparam.h
+index ea7546c..fb8493f 100644
+--- a/bsd-user/i386/target_vmparam.h
++++ b/bsd-user/i386/target_vmparam.h
+@@ -1,8 +1,19 @@
+ #ifndef _TARGET_VMPARAM_H_
+ #define _TARGET_VMPARAM_H_
+
++#define TARGET_HW_MACHINE "i386"
++#define TARGET_HW_MACHINE_ARCH "i386"
++
+ #if defined(__FreeBSD__)
+
++/* 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_USRSTACK (0xbfc00000)
+
+ struct target_ps_strings {
+@@ -19,10 +30,6 @@ struct target_ps_strings {
+
+ #define TARGET_SZSIGCODE 0
+
+-/* Make stack size large enough to hold everything. */
+-#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
+- MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
+-
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/main.c b/bsd-user/main.c
+index b248a91..99b94c1 100644
+--- a/bsd-user/main.c
++++ b/bsd-user/main.c
+@@ -56,10 +56,15 @@ const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
+ extern char **environ;
+ enum BSDType bsd_type;
+
++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 */
+ /* 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;
++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 void save_proc_pathname(void);
+ char qemu_proc_pathname[PATH_MAX];
+@@ -126,7 +131,7 @@ static int pending_cpus;
+ /* Make sure everything is in a consistent state for calling fork(). */
+ void fork_start(void)
+ {
+- pthread_mutex_lock(&tb_lock);
++ spin_lock(&tb_lock);
+ pthread_mutex_lock(&exclusive_lock);
+ mmap_fork_start();
+ }
+@@ -146,11 +151,11 @@ void fork_end(int child)
+ pthread_mutex_init(&cpu_list_mutex, NULL);
+ pthread_cond_init(&exclusive_cond, NULL);
+ pthread_cond_init(&exclusive_resume, NULL);
+- pthread_mutex_init(&tb_lock, NULL);
++ spin_lock_init(&tb_lock);
+ gdbserver_fork(thread_env);
+ } else {
+ pthread_mutex_unlock(&exclusive_lock);
+- pthread_mutex_unlock(&tb_lock);
++ spin_unlock(&tb_lock);
+ }
+ }
+
+@@ -1012,10 +1017,7 @@ void cpu_loop(CPUMIPSState *env)
+
+ for(;;) {
+ cpu_exec_start(env);
+- /* XXX there is a concurrency problem - giant lock for now */
+- pthread_mutex_lock(&exclusive_lock); /* XXX */
+ trapnr = cpu_mips_exec(env);
+- pthread_mutex_unlock(&exclusive_lock); /* XXX */
+ cpu_exec_end(env);
+ switch(trapnr) {
+ case EXCP_SYSCALL: /* syscall exception */
+@@ -1481,7 +1483,7 @@ static void usage(void)
+ ,
+ TARGET_ARCH,
+ interp_prefix,
+- x86_stack_size,
++ target_dflssiz,
+ DEBUG_LOGFILE);
+ exit(1);
+ }
+@@ -1603,13 +1605,15 @@ 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')
+- x86_stack_size *= 1024 * 1024;
++ target_dflssiz *= 1024 * 1024;
+ else if (*r == 'k' || *r == 'K')
+- x86_stack_size *= 1024;
++ target_dflssiz *= 1024;
++ if (target_dflssiz > target_maxssiz)
++ usage();
+ } else if (!strcmp(r, "L")) {
+ interp_prefix = argv[optind++];
+ } else if (!strcmp(r, "p")) {
+@@ -1797,7 +1801,7 @@ int main(int argc, char **argv)
+ qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry);
+ }
+
+- target_set_brk(info->brk);
++ target_set_brk(info->start_data, info->brk, info->end_data);
+ syscall_init();
+ signal_init();
+
+diff --git a/bsd-user/mips/target_signal.h b/bsd-user/mips/target_signal.h
+index 0f57f0f..abe4587 100644
+--- a/bsd-user/mips/target_signal.h
++++ b/bsd-user/mips/target_signal.h
+@@ -6,6 +6,10 @@
+ #define TARGET_MINSIGSTKSZ (512 * 4)
+ #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
+
++/* compare to sys/mips/include/asm.h */
++#define TARGET_SZREG 4
++#define TARGET_CALLFRAME_SIZ (TARGET_SZREG * 4)
++
+ struct target_sigcontext {
+ target_sigset_t sc_mask; /* signal mask to retstore */
+ int32_t sc_onstack; /* sigstack state to restore */
+@@ -207,4 +211,27 @@ get_ucontext_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr,
+ return (0);
+ }
+
++/* Compare to mips/mips/vm_machdep.c cpu_set_upcall_kse() */
++static inline void
++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;
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/mips/target_vmparam.h b/bsd-user/mips/target_vmparam.h
+index 8abc26c..6eca54f 100644
+--- a/bsd-user/mips/target_vmparam.h
++++ b/bsd-user/mips/target_vmparam.h
+@@ -1,7 +1,19 @@
+ #ifndef _TARGET_VMPARAM_H_
+ #define _TARGET_VMPARAM_H_
+
++#define TARGET_HW_MACHINE "mips"
++#define TARGET_HW_MACHINE_ARCH "mips"
++
+ #if defined(__FreeBSD__)
++
++/* 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 (0x00000000)
+ #define TARGET_VM_MAXUSER_ADDRESS (0x80000000)
+
+@@ -21,10 +33,6 @@ struct target_ps_strings {
+
+ #define TARGET_SZSIGCODE 0
+
+-/* Make stack size large enough to hold everything. */
+-#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
+- MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
+-
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h
+index 3fee772..60105ec 100644
+--- a/bsd-user/mips64/target_signal.h
++++ b/bsd-user/mips64/target_signal.h
+@@ -6,6 +6,10 @@
+ #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)
++
+ struct target_sigcontext {
+ target_sigset_t sc_mask; /* signal mask to retstore */
+ int32_t sc_onstack; /* sigstack state to restore */
+@@ -226,5 +230,28 @@ get_ucontext_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr,
+ return (0);
+ }
+
++/* Compare to mips/mips/vm_machdep.c cpu_set_upcall_kse() */
++static inline void
++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;
++}
++
+ #endif /* TARGET_SIGNAL_H */
+
+diff --git a/bsd-user/mips64/target_vmparam.h b/bsd-user/mips64/target_vmparam.h
+index 55ed254..3fe93fb 100644
+--- a/bsd-user/mips64/target_vmparam.h
++++ b/bsd-user/mips64/target_vmparam.h
+@@ -1,8 +1,19 @@
+ #ifndef _TARGET_VMPARAM_H_
+ #define _TARGET_VMPARAM_H_
+
++#define TARGET_HW_MACHINE "mips"
++#define TARGET_HW_MACHINE_ARCH "mips64"
++
+ #if defined(__FreeBSD__)
+
++/* 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)
+
+@@ -20,10 +31,6 @@ struct target_ps_strings {
+
+ #define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings))
+
+-/* Make stack size large enough to hold everything. */
+-#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
+- MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
+-
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
+index 495f0ec..1ed597a 100644
+--- a/bsd-user/mmap.c
++++ b/bsd-user/mmap.c
+@@ -31,8 +31,8 @@
+ //#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)
+ {
+@@ -348,6 +348,9 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+ case MAP_SHARED:
+ printf("MAP_SHARED ");
+ break;
++ case MAP_STACK:
++ printf("MAP_STACK ");
++ break;
+ default:
+ printf("[MAP_FLAGMASK=0x%x] ", flags & TARGET_BSD_MAP_FLAGMASK);
+ break;
+@@ -356,6 +359,14 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
+ }
+ #endif
+
++ if (flags & MAP_STACK) {
++ if ((fd != -1) ||
++ ((prot & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE))) {
++ errno = EINVAL;
++ goto fail;
++ }
++ }
++
+ if (offset & ~TARGET_PAGE_MASK) {
+ errno = EINVAL;
+ goto fail;
+diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
+index fbcdd6c..4c20e48 100644
+--- a/bsd-user/qemu.h
++++ b/bsd-user/qemu.h
+@@ -147,7 +147,7 @@ int load_flt_binary(struct bsd_binprm * bprm, struct target_pt_regs * regs,
+ struct image_info * info);
+ int is_target_elf_binary(int fd);
+
+-void target_set_brk(abi_ulong new_brk);
++void target_set_brk(abi_ulong start_brk, abi_ulong cur_brk, abi_ulong end_brk);
+ abi_long do_brk(abi_ulong new_brk);
+ void syscall_init(void);
+ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+@@ -221,7 +221,12 @@ 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[];
+ extern char target_proc_pathname[];
+
+diff --git a/bsd-user/signal.c b/bsd-user/signal.c
+index e7e9e41..c4e8440 100644
+--- a/bsd-user/signal.c
++++ b/bsd-user/signal.c
+@@ -631,7 +631,7 @@ get_sigframe(struct target_sigaction *ka, CPUArchState *regs, size_t frame_size)
+ target_sigaltstack_used.ss_size;
+ }
+
+-#if defined(TARGET_MIPS)
++#if defined(TARGET_MIPS) || defined(TARGET_ARM)
+ return ((sp - frame_size) & ~7);
+ #else
+ return (sp - frame_size);
+diff --git a/bsd-user/sparc/target_signal.h b/bsd-user/sparc/target_signal.h
+index 65d315a..20630d7 100644
+--- a/bsd-user/sparc/target_signal.h
++++ b/bsd-user/sparc/target_signal.h
+@@ -51,4 +51,12 @@ get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
+ return (-TARGET_ENOSYS);
+ }
+
++/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */
++static inline void
++thread_set_upcall(CPUArchState *regs, abi_ulong entry, abi_ulong arg,
++ abi_ulong stack_base, abi_ulong stack_size)
++{
++ fprintf(stderr, "SPARC doesn't have support for thread_set_upcall()\n");
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/sparc/target_vmparam.h b/bsd-user/sparc/target_vmparam.h
+index 82c29ed..b8dcd0d 100644
+--- a/bsd-user/sparc/target_vmparam.h
++++ b/bsd-user/sparc/target_vmparam.h
+@@ -1,7 +1,18 @@
+ #ifndef _TARGET_VMPARAM_H_
+ #define _TARGET_VMPARAM_H_
+
++#define TARGET_HW_MACHINE "sparc"
++#define TARGET_HW_MACHINE_ARCH "sparc"
++
+ #ifdef __FreeBSD__
++
++#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 */
++
+ struct target_ps_strings {
+ abi_ulong ps_argvstr;
+ uint32_t ps_nargvstr;
+@@ -20,10 +31,6 @@ struct target_ps_strings {
+
+ #define TARGET_SZSIGCODE 0
+
+-/* Make stack size large enough to hold everything. */
+-#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
+- MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
+-
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/sparc64/target_signal.h b/bsd-user/sparc64/target_signal.h
+index fa8edb8..67378a5 100644
+--- a/bsd-user/sparc64/target_signal.h
++++ b/bsd-user/sparc64/target_signal.h
+@@ -253,4 +253,12 @@ get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
+ return (-TARGET_ENOSYS);
+ }
+
++/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */
++static inline void
++thread_set_upcall(CPUArchState *regs, abi_ulong entry, abi_ulong arg,
++ abi_ulong stack_base, abi_ulong stack_size)
++{
++ fprintf(stderr, "SPARC64 doesn't have support for thread_set_upcall()\n");
++}
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/sparc64/target_vmparam.h b/bsd-user/sparc64/target_vmparam.h
+index 7f2b464..b8dbf2c 100644
+--- a/bsd-user/sparc64/target_vmparam.h
++++ b/bsd-user/sparc64/target_vmparam.h
+@@ -1,7 +1,19 @@
+ #ifndef _TARGET_VMPARAM_H_
+ #define _TARGET_VMPARAM_H_
+
++#define TARGET_HW_MACHINE "sparc"
++#define TARGET_HW_MACHINE_ARCH "sparc64"
++
+ #if defined(__FreeBSD__)
++
++/* 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 */
++
+ #define TARGET_VM_MINUSER_ADDRESS (0x0000000000000000UL)
+ #define TARGET_VM_MAXUSER_ADDRESS (0x000007fe00000000UL)
+
+@@ -21,10 +33,6 @@ struct target_ps_strings {
+
+ #define TARGET_SZSIGCODE 0
+
+-/* Make stack size large enough to hold everything. */
+-#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
+- MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
+-
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
+index 2d97a23..0f337e2 100644
+--- a/bsd-user/syscall.c
++++ b/bsd-user/syscall.c
+@@ -98,8 +98,7 @@
+
+ //#define DEBUG
+
+-static abi_ulong target_brk;
+-static abi_ulong target_original_brk;
++static abi_ulong target_brk_start, target_brk_cur, target_brk_end;
+
+ static char *get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len);
+
+@@ -123,6 +122,7 @@ get_filename_from_fd(pid_t pid, int fd, char *filename, size_t len)
+ struct filestat *fst;
+ char *ret = NULL;
+
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ procstat = procstat_open_sysctl();
+ if (NULL == procstat)
+ goto out;
+@@ -152,6 +152,7 @@ out:
+ procstat_freeprocs(procstat, kipp);
+ if (procstat != NULL)
+ procstat_close(procstat);
++#endif
+ return (ret);
+ }
+
+@@ -188,41 +189,45 @@ static inline int is_error(abi_long ret)
+ return (abi_ulong)ret >= (abi_ulong)(-4096);
+ }
+
+-void target_set_brk(abi_ulong new_brk)
++void target_set_brk(abi_ulong start_brk, abi_ulong cur_brk, abi_ulong end_brk)
+ {
+- target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
++ target_brk_start = HOST_PAGE_ALIGN(start_brk);
++ target_brk_cur = cur_brk;
++ target_brk_end = HOST_PAGE_ALIGN(end_brk);
+ }
+
+ /* 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;
++ abi_ulong new_alloc_size;
++
++ return -TARGET_EINVAL; // XXX Temporary disable obreak() until it can be properly fixed
+
+ if (!new_brk)
+ return 0;
+- if (new_brk < target_original_brk)
++ if (new_brk < target_brk_cur) {
+ return -TARGET_EINVAL;
+-
+- brk_page = HOST_PAGE_ALIGN(target_brk);
++ }
+
+ /* If the new brk is less than this, set it and we're done... */
+- if (new_brk < brk_page) {
+- target_brk = new_brk;
++ if (new_brk < target_brk_end) {
++ target_brk_cur = 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,
++ new_alloc_size = HOST_PAGE_ALIGN(new_brk - target_brk_end + 1);
++ mapped_addr = get_errno(target_mmap(target_brk_end, new_alloc_size,
+ PROT_READ|PROT_WRITE,
+ MAP_ANON|MAP_FIXED|MAP_PRIVATE, -1, 0));
+
+- if (!is_error(mapped_addr))
+- target_brk = new_brk;
+- else
++ if (!is_error(mapped_addr)) {
++ target_brk_cur = new_brk;
++ target_brk_end += new_alloc_size;
++ } else {
+ return mapped_addr;
++ }
+
+ return 0;
+ }
+@@ -520,11 +525,7 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol
+ case CTL_KERN:
+ switch(snamep[1]) {
+ case KERN_USRSTACK:
+-#if defined(TARGET_ARM) && HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
+- (*(uint32_t *)holdp) = 0xfffff000U;
+- holdlen = sizeof(uint32_t);
+- ret = 0;
+-#elif TARGET_USRSTACK != 0
++#if TARGET_USRSTACK != 0
+ (*(abi_ulong *)holdp) = tswapal(TARGET_USRSTACK);
+ holdlen = sizeof(abi_ulong);
+ ret = 0;
+@@ -568,6 +569,22 @@ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong ol
+ }
+ 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;
++
++ default:
++ break;
++ }
++
+ default:
+ break;
+ }
+@@ -1736,7 +1753,9 @@ int_case:
+ case IP_RECVDSTADDR:
+
+ case IP_RETOPTS:
++#if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ case IP_RECVTOS:
++#endif
+ case IP_MULTICAST_TTL:
+ case IP_MULTICAST_LOOP:
+ case IP_PORTRANGE:
+@@ -2553,7 +2572,7 @@ do_fork(CPUArchState *env, int num, int flags, int *fdp)
+ static pthread_mutex_t new_thread_lock = PTHREAD_MUTEX_INITIALIZER;
+ typedef struct {
+ CPUArchState *env;
+- long tid;
++ long parent_tid;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ pthread_t thread;
+@@ -2571,24 +2590,23 @@ new_thread_start(void *arg)
+
+ env = info->env;
+ thread_env = env;
++ fork_end(1);
++
+ ts = (TaskState *)thread_env->opaque;
+ (void)thr_self(&tid);
+- info->tid = tid;
+ task_settid(ts);
+
+ /* copy out the TID info */
+ if (info->param.child_tid)
+ put_user(tid, info->param.child_tid, abi_long);
+ if (info->param.parent_tid)
+- put_user(tid, info->param.parent_tid, abi_long);
++ put_user(info->parent_tid, info->param.parent_tid, abi_long);
+
+-#ifdef TARGET_MIPS64
+- CPUMIPSState *regs = env;
+- regs->active_tc.gpr[25] = regs->active_tc.PC = info->param.start_func;
+- regs->active_tc.gpr[ 4] = info->param.arg;
+- regs->active_tc.gpr[29] = info->param.stack_base;
+-#endif
+- /* Eenable signals */
++ /* Set arch dependent registers to start thread. */
++ 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);
+@@ -2662,9 +2680,12 @@ do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size)
+ 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))
+@@ -2678,6 +2699,7 @@ do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size)
+ }
+
+ /* Create a new CPU instance. */
++ fork_start();
+ ts = g_malloc0(sizeof(TaskState));
+ init_task_state(ts);
+ new_env = cpu_copy(env);
+@@ -2691,9 +2713,8 @@ do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size)
+ ts->bprm = parent_ts->bprm;
+ ts->info = parent_ts->info;
+
+-#if defined(TARGET_MIPS)
+- env->tls_value = info.param.tls_base;
+- /* cpu_set_tls(new_env, info.param.tls_base); */
++#if defined(TARGET_MIPS) || defined(TARGET_ARM)
++ cpu_set_tls(env, info.param.tls_base);
+ #endif
+
+ /* Grab a mutex so that thread setup appears atomic. */
+@@ -2725,6 +2746,8 @@ do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size)
+ ret = pthread_create(&info.thread, &attr, new_thread_start, &info);
+ /* XXX Free new CPU state if thread creation fails. */
+
++ fork_end(0);
++
+ sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
+ pthread_attr_destroy(&attr);
+ if (0 == ret) {
+@@ -2791,6 +2814,9 @@ do_thr_exit(CPUArchState *cpu_env, abi_ulong tid_addr)
+ g_free(ts);
+ pthread_exit(NULL);
+ }
++
++ gdb_exit(cpu_env, 0); /* XXX need to put in the correct exit status here? */
++ _exit(0);
+ }
+
+ static int
+@@ -3010,7 +3036,7 @@ do_lock_umutex(abi_ulong target_addr, uint32_t id, struct timespec *ts,
+ int mode)
+ {
+ uint32_t owner, flags;
+- int ret;
++ int ret = 0;
+
+ for (;;) {
+ struct target_umutex *target_umutex;
+@@ -3058,7 +3084,6 @@ do_lock_umutex(abi_ulong target_addr, uint32_t id, struct timespec *ts,
+ }
+
+ __get_user(flags, &target_umutex->m_flags);
+- flags = tswap32(flags);
+ if ((flags & TARGET_UMUTEX_ERROR_CHECK) != 0 &&
+ (owner & ~TARGET_UMUTEX_CONTESTED) == id) {
+ unlock_user_struct(target_umutex, target_addr, 1);
+@@ -3070,6 +3095,15 @@ do_lock_umutex(abi_ulong target_addr, uint32_t id, struct timespec *ts,
+ return (-TARGET_EBUSY);
+ }
+
++ /*
++ * If we caught a signal, we have retried and now
++ * exit immediately.
++ */
++ if (ret) {
++ unlock_user_struct(target_umutex, target_addr, 1);
++ return (ret);
++ }
++
+ /* Set the contested bit and sleep. */
+ if (!tcmpset_32(&target_umutex->m_owner, owner,
+ owner | TARGET_UMUTEX_CONTESTED)) {
+@@ -3084,8 +3118,6 @@ do_lock_umutex(abi_ulong target_addr, uint32_t id, struct timespec *ts,
+ owner = tswap32(owner);
+ ret = get_errno(_umtx_op(target_umutex, UMTX_OP_WAIT_UINT, owner,
+ 0, ts));
+- if (ret)
+- return (ret);
+ }
+
+ return (0);
+@@ -4841,8 +4873,9 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ case TARGET_FREEBSD_NR_fstat:
+ {
+ struct stat st;
++
+ ret = get_errno(fstat(arg1, &st));
+- if (! ret)
++ if (!is_error(ret))
+ ret = host_to_target_stat(arg2, &st);
+ }
+ break;
+@@ -4851,10 +4884,12 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ {
+ struct timespec req, rem;
+
+- target_to_host_timespec(&req, arg1);
+- ret = get_errno(nanosleep(&req, &rem));
+- if (is_error(ret) && arg2)
+- host_to_target_timespec(arg2, &rem);
++ ret = target_to_host_timespec(&req, arg1);
++ if (!is_error(ret)) {
++ ret = get_errno(nanosleep(&req, &rem));
++ if (!is_error(ret) && arg2)
++ host_to_target_timespec(arg2, &rem);
++ }
+ }
+ break;
+
+@@ -5119,12 +5154,23 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+ struct target_rlimit *target_rlim;
+ struct rlimit rlim;
+
+- /* Return the target stack size */
+- if (RLIMIT_STACK == resource) {
+- rlim.rlim_cur = rlim.rlim_max = TARGET_STACK_SIZE;
++ switch (resource) {
++ case RLIMIT_STACK:
++ rlim.rlim_cur = target_dflssiz;
++ rlim.rlim_max = target_maxssiz;
+ ret = 0;
+- } else
++ 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))
+@@ -7260,11 +7306,28 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
+
+ #if defined(__FreeBSD_version) && __FreeBSD_version > 900000
+ case TARGET_UMTX_OP_NWAKE_PRIVATE:
+- if (! access_ok(VERIFY_READ, obj,
+- val * sizeof(uint32_t)))
+- goto efault;
+- ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_NWAKE_PRIVATE,
+- val, NULL, NULL));
++ {
++ int i;
++ abi_ulong *uaddr;
++
++ if (! access_ok(VERIFY_READ, obj,
++ val * sizeof(uint32_t)))
++ goto efault;
++
++ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_NWAKE_PRIVATE,
++ val, NULL, NULL));
++
++ uaddr = (abi_ulong *)g2h(obj);
++ ret = 0;
++ for(i = 0; i < (int32_t)val; i++) {
++ ret = get_errno(_umtx_op(g2h(tswapal(uaddr[i])),
++ UMTX_OP_WAKE_PRIVATE, tswap32(INT_MAX),
++ NULL, NULL));
++ if (ret)
++ break;
++ }
++
++ }
+ break;
+ #endif
+
+diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
+index eb804b3..c2e78bd 100644
+--- a/bsd-user/syscall_defs.h
++++ b/bsd-user/syscall_defs.h
+@@ -544,6 +544,7 @@ struct target_thr_param {
+ 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. */
+ };
+diff --git a/bsd-user/x86_64/target_signal.h b/bsd-user/x86_64/target_signal.h
+index 72df2f0..51e32bf 100644
+--- a/bsd-user/x86_64/target_signal.h
++++ b/bsd-user/x86_64/target_signal.h
+@@ -49,4 +49,13 @@ get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
+ return (-TARGET_ENOSYS);
+ }
+
++/* Compare to arm/arm/vm_machdep.c cpu_set_upcall_kse() */
++static inline void
++thread_set_upcall(CPUArchState *regs, abi_ulong entry, abi_ulong arg,
++ abi_ulong stack_base, abi_ulong stack_size)
++{
++ fprintf(stderr, "x86_64 doesn't have support for thread_set_upcall()\n");
++}
++
++
+ #endif /* TARGET_SIGNAL_H */
+diff --git a/bsd-user/x86_64/target_vmparam.h b/bsd-user/x86_64/target_vmparam.h
+index ff9f534..70891a1 100644
+--- a/bsd-user/x86_64/target_vmparam.h
++++ b/bsd-user/x86_64/target_vmparam.h
+@@ -1,7 +1,19 @@
+ #ifndef _TARGET_VMPARAM_H_
+ #define _TARGET_VMPARAM_H_
+
++#define TARGET_HW_MACHINE "amd64"
++#define TARGET_HW_MACHINE_ARCH "amd64"
++
+ #if defined(__FreeBSD__)
++
++/* 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)
+@@ -20,10 +32,6 @@ struct target_ps_strings {
+
+ #define TARGET_SZSIGCODE 0
+
+-/* Make stack size large enough to hold everything. */
+-#define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \
+- MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size)
+-
+ #else
+
+ #define TARGET_USRSTACK 0
+diff --git a/include/exec/spinlock.h b/include/exec/spinlock.h
+index a72edda..fc1f808 100644
+--- a/include/exec/spinlock.h
++++ b/include/exec/spinlock.h
+@@ -24,6 +24,7 @@
+ #include <pthread.h>
+ #define spin_lock pthread_mutex_lock
+ #define spin_unlock pthread_mutex_unlock
++#define spin_lock_init(mtx) pthread_mutex_init(mtx, NULL)
+ #define spinlock_t pthread_mutex_t
+ #define SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
+
+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