diff options
| author | Juergen Lock <nox@FreeBSD.org> | 2013-03-29 17:40:38 +0000 |
|---|---|---|
| committer | Juergen Lock <nox@FreeBSD.org> | 2013-03-29 17:40:38 +0000 |
| commit | 45aa9370f03dfaf05a98af04f0addd7e3998d771 (patch) | |
| tree | d33294058708ce0ec0faa156a7ed184dea6cdc1d /emulators/qemu-devel/files/patch-z2c-bsd-user-sson-002c | |
| parent | - (force commit to note) add new port: games/chessx (diff) | |
- Update net/usbredir to 0.6 .
- Update emulators/qemu-devel to 1.4.0 with preliminary bsd-user patches.
Thanx to: sson, cognet, and others for much improved bsd-user support -
it now runs at least quite a few mips64 and single-threaded
arm binaries, see:
https://wiki.freebsd.org/QemuUserModeHowTo
Diffstat (limited to 'emulators/qemu-devel/files/patch-z2c-bsd-user-sson-002c')
| -rw-r--r-- | emulators/qemu-devel/files/patch-z2c-bsd-user-sson-002c | 2301 |
1 files changed, 2301 insertions, 0 deletions
diff --git a/emulators/qemu-devel/files/patch-z2c-bsd-user-sson-002c b/emulators/qemu-devel/files/patch-z2c-bsd-user-sson-002c new file mode 100644 index 000000000000..e0f024151e70 --- /dev/null +++ b/emulators/qemu-devel/files/patch-z2c-bsd-user-sson-002c @@ -0,0 +1,2301 @@ +diff --git a/bsd-user/arm/target_signal.h b/bsd-user/arm/target_signal.h +index 19cc188..6b7bb67 100644 +--- a/bsd-user/arm/target_signal.h ++++ b/bsd-user/arm/target_signal.h +@@ -11,4 +11,29 @@ static inline abi_ulong get_sp_from_cpustate(CPUARMState *state) + #define TARGET_MINSIGSTKSZ (1024 * 4) + #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) + ++typedef target_ulong target_mcontext_t; /* dummy */ ++ ++typedef struct target_ucontext { ++ target_sigset_t uc_sigmask; ++ target_mcontext_t uc_mcontext; ++ abi_ulong uc_link; ++ target_stack_t uc_stack; ++ int32_t uc_flags; ++ int32_t __spare__[4]; ++} target_ucontext_t; ++ ++static inline int ++get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags) ++{ ++ fprintf(stderr, "ARM doesn't have support for get_mcontext()\n"); ++ return (-TARGET_ENOSYS); ++} ++ ++static inline int ++set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags) ++{ ++ fprintf(stderr, "ARM doesn't have support for set_mcontext()\n"); ++ return (-TARGET_ENOSYS); ++} ++ + #endif /* TARGET_SIGNAL_H */ +diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list +index 1edf412..b09f766 100644 +--- a/bsd-user/freebsd/strace.list ++++ b/bsd-user/freebsd/strace.list +@@ -38,6 +38,7 @@ + { TARGET_FREEBSD_NR_fsync, "fsync", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_ftruncate, "ftruncate", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_futimes, "futimes", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_getcontext, "getcontext", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_getdirentries, "getdirentries", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_freebsd6_mmap, "freebsd6_mmap", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_getegid, "getegid", "%s()", NULL, NULL }, +@@ -123,6 +124,7 @@ + { TARGET_FREEBSD_NR_semop, "semop", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_sendmsg, "sendmsg", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_sendto, "sendto", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_setcontext, "setcontext", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_setegid, "setegid", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_seteuid, "seteuid", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_setgid, "setgid", NULL, NULL, NULL }, +@@ -160,6 +162,15 @@ + { TARGET_FREEBSD_NR_sync, "sync", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_sysarch, "sysarch", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_syscall, "syscall", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_thr_create, "thr_create", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_thr_exit, "thr_exit", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_thr_kill, "thr_kill", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_thr_kill2, "thr_kill2", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_thr_new, "thr_new", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_thr_self, "thr_self", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_thr_set_name, "thr_set_name", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_thr_suspend, "thr_suspend", NULL, NULL, NULL }, ++{ TARGET_FREEBSD_NR_thr_wake, "thr_wake", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_truncate, "truncate", NULL, NULL, NULL }, + { TARGET_FREEBSD_NR_umask, "umask", "%s(%#o)", NULL, NULL }, + { TARGET_FREEBSD_NR_unlink, "unlink", "%s(\"%s\")", NULL, NULL }, +diff --git a/bsd-user/i386/target_signal.h b/bsd-user/i386/target_signal.h +index 285e7f9..28481ce 100644 +--- a/bsd-user/i386/target_signal.h ++++ b/bsd-user/i386/target_signal.h +@@ -11,4 +11,29 @@ static inline abi_ulong get_sp_from_cpustate(CPUX86State *state) + #define TARGET_MINSIGSTKSZ (512 * 4) + #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) + ++typedef target_ulong target_mcontext_t; /* dummy */ ++ ++typedef struct target_ucontext { ++ target_sigset_t uc_sigmask; ++ target_mcontext_t uc_mcontext; ++ abi_ulong uc_link; ++ target_stack_t uc_stack; ++ int32_t uc_flags; ++ int32_t __spare__[4]; ++} target_ucontext_t; ++ ++static inline int ++get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags) ++{ ++ fprintf(stderr, "i386 doesn't have support for get_mcontext()\n"); ++ return (-TARGET_ENOSYS); ++} ++ ++static inline int ++set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags) ++{ ++ fprintf(stderr, "i386 doesn't have support for set_mcontext()\n"); ++ return (-TARGET_ENOSYS); ++} ++ + #endif /* TARGET_SIGNAL_H */ +diff --git a/bsd-user/main.c b/bsd-user/main.c +index 146f022..7a99537 100644 +--- a/bsd-user/main.c ++++ b/bsd-user/main.c +@@ -34,6 +34,10 @@ + #include "qemu-timer.h" + #include "envlist.h" + ++#if defined(CONFIG_USE_NPTL) && defined(__FreeBSD__) ++#include <sys/thr.h> ++#endif ++ + #define DEBUG_LOGFILE "/tmp/qemu.log" + + int singlestep; +@@ -70,42 +74,186 @@ int cpu_get_pic_interrupt(CPUX86State *env) + } + #endif + +-/* These are no-ops because we are not threadsafe. */ +-static inline void cpu_exec_start(CPUArchState *env) ++#if defined(CONFIG_USE_NPTL) ++/* Helper routines for implementing atomic operations. */ ++ ++/* ++ * To implement exclusive operations we force all cpus to synchronize. ++ * We don't require a full sync, only that no cpus are executing guest code. ++ * The alternative is to map target atomic ops onto host eqivalents, ++ * which requires quite a lot of per host/target work. ++ */ ++static pthread_mutex_t cpu_list_mutex = PTHREAD_MUTEX_INITIALIZER; ++static pthread_mutex_t exclusive_lock = PTHREAD_MUTEX_INITIALIZER; ++static pthread_cond_t exclusive_cond = PTHREAD_COND_INITIALIZER; ++static pthread_cond_t exclusive_resume = PTHREAD_COND_INITIALIZER; ++static int pending_cpus; ++ ++/* Make sure everything is in a consistent state for calling fork(). */ ++void fork_start(void) + { ++ pthread_mutex_lock(&tb_lock); ++ pthread_mutex_lock(&exclusive_lock); ++ mmap_fork_start(); + } + +-static inline void cpu_exec_end(CPUArchState *env) ++void fork_end(int child) + { ++ mmap_fork_end(child); ++ if (child) { ++ /* ++ * Child processes created by fork() only have a single thread. ++ * Discard information about the parent threads. ++ */ ++ first_cpu = thread_env; ++ thread_env->next_cpu = NULL; ++ pending_cpus = 0; ++ pthread_mutex_init(&exclusive_lock, NULL); ++ pthread_mutex_init(&cpu_list_mutex, NULL); ++ pthread_cond_init(&exclusive_cond, NULL); ++ pthread_cond_init(&exclusive_resume, NULL); ++ pthread_mutex_init(&tb_lock, NULL); ++ gdbserver_fork(thread_env); ++ } else { ++ pthread_mutex_unlock(&exclusive_lock); ++ pthread_mutex_unlock(&tb_lock); ++ } + } + +-static inline void start_exclusive(void) ++/* ++ * Wait for pending exclusive operations to complete. The exclusive lock ++ * must be held. ++ */ ++static inline void ++exclusive_idle(void) + { ++ while (pending_cpus) { ++ pthread_cond_wait(&exclusive_resume, &exclusive_lock); ++ } + } + +-static inline void end_exclusive(void) ++/* Start an exclusive operation. Must only be called outside of cpu_exec. */ ++static inline void ++start_exclusive(void) + { ++ CPUArchState *other; ++ ++ pthread_mutex_lock(&exclusive_lock); ++ exclusive_idle(); ++ ++ pending_cpus = 1; ++ /* Make all other cpus stop executing. */ ++ for (other = first_cpu; other; other = other->next_cpu) { ++ if (other->running) { ++ pending_cpus++; ++ cpu_exit(other); ++ } ++ } ++ if (pending_cpus > 1) { ++ pthread_cond_wait(&exclusive_cond, &exclusive_lock); ++ } + } + +-void fork_start(void) ++/* Finish an exclusive operation. */ ++static inline void ++end_exclusive(void) + { ++ pending_cpus = 0; ++ pthread_cond_broadcast(&exclusive_resume); ++ pthread_mutex_unlock(&exclusive_lock); + } + +-void fork_end(int child) ++/* Wait for exclusive ops to finish, and begin cpu execution. */ ++static inline void ++cpu_exec_start(CPUArchState *env) ++{ ++ pthread_mutex_lock(&exclusive_lock); ++ exclusive_idle(); ++ env->running = 1; ++ pthread_mutex_unlock(&exclusive_lock); ++} ++ ++/* Mark cpu as not excuting, and release pending exclusive ops. */ ++static inline void ++cpu_exec_end(CPUArchState *env) ++{ ++ pthread_mutex_lock(&exclusive_lock); ++ env->running = 0; ++ if (pending_cpus > 1) { ++ pending_cpus--; ++ if (pending_cpus == 1) { ++ pthread_cond_signal(&exclusive_cond); ++ } ++ } ++ exclusive_idle(); ++ pthread_mutex_unlock(&exclusive_lock); ++} ++ ++void ++cpu_list_lock(void) ++{ ++ pthread_mutex_lock(&cpu_list_mutex); ++} ++ ++void ++cpu_list_unlock(void) ++{ ++ pthread_mutex_unlock(&cpu_list_mutex); ++} ++ ++#else /* ! CONFIG_USE_NPTL */ ++ ++/* These are no-ops because we are not threadsafe. */ ++void ++fork_start(void) ++{ ++} ++ ++void ++fork_end(int child) + { + if (child) { + gdbserver_fork(thread_env); + } + } + +-void cpu_list_lock(void) ++static inline void ++exclusive_idle(void) ++{ ++} ++ ++static inline void ++start_exclusive(void) + { + } + +-void cpu_list_unlock(void) ++static inline void ++end_exclusive(void) + { + } + ++static inline void ++cpu_exec_start(CPUArchState *env) ++{ ++} ++ ++ ++static inline void ++cpu_exec_end(CPUArchState *env) ++{ ++} ++ ++void ++cpu_list_lock(void) ++{ ++} ++ ++void ++cpu_list_unlock(void) ++{ ++} ++#endif /* CONFIG_USE_NPTL */ ++ + #ifdef TARGET_I386 + /***********************************************************/ + /* CPUX86 core interface */ +@@ -740,7 +888,10 @@ void cpu_loop(CPUMIPSState *env) + + for(;;) { + cpu_exec_start(env); ++ /* XXX there is a concurrency problem - giant lock for now */ ++ pthread_mutex_lock(&exclusive_lock); /* XXX */ + trapnr = cpu_mips_exec(env); ++ pthread_mutex_unlock(&exclusive_lock); /* XXX */ + cpu_exec_end(env); + switch(trapnr) { + case EXCP_SYSCALL: /* syscall exception */ +@@ -1206,6 +1357,18 @@ static void usage(void) + + THREAD CPUArchState *thread_env; + ++void task_settid(TaskState *ts) ++{ ++ if (0 == ts->ts_tid) { ++#ifdef CONFIG_USE_NPTL ++ (void)thr_self(&ts->ts_tid); ++#else ++ /* When no threads then just use PID */ ++ ts->ts_tid = getpid(); ++#endif ++ } ++} ++ + void stop_all_tasks(void) + { + /* +diff --git a/bsd-user/mips/target_signal.h b/bsd-user/mips/target_signal.h +index 28871c3..484cfd8 100644 +--- a/bsd-user/mips/target_signal.h ++++ b/bsd-user/mips/target_signal.h +@@ -6,9 +6,187 @@ + #define TARGET_MINSIGSTKSZ (512 * 4) + #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) + +-static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) ++struct target_sigcontext { ++ target_sigset_t sc_mask; /* signal mask to retstore */ ++ int32_t sc_onstack; /* sigstack state to restore */ ++ abi_long sc_pc; /* pc at time of signal */ ++ abi_long sc_reg[32]; /* processor regs 0 to 31 */ ++ abi_long mullo, mulhi; /* mullo and mulhi registers */ ++ int32_t sc_fpused; /* fp has been used */ ++ abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */ ++ abi_long sc_fpc_eir; /* fp exception instr reg */ ++ /* int32_t reserved[8]; */ ++}; ++ ++typedef struct target_mcontext { ++ int32_t mc_onstack; /* sigstack state to restore */ ++ abi_long mc_pc; /* pc at time of signal */ ++ abi_long mc_regs[32]; /* process regs 0 to 31 */ ++ abi_long sr; /* status register */ ++ abi_long mullo, mulhi; ++ int32_t mc_fpused; /* fp has been used */ ++ abi_long mc_fpregs[33]; /* fp regs 0 to 32 & csr */ ++ abi_long mc_fpc_eir; /* fp exception instr reg */ ++ abi_ulong mc_tls; /* pointer to TLS area */ ++} target_mcontext_t; ++ ++typedef struct target_ucontext { ++ target_sigset_t uc_sigmask; ++ target_mcontext_t uc_mcontext; ++ abi_ulong uc_link; ++ target_stack_t uc_stack; ++ int32_t uc_flags; ++ int32_t __spare__[4]; ++} target_ucontext_t; ++ ++struct target_sigframe { ++ abi_ulong sf_signum; ++ abi_ulong sf_siginfo; /* code or pointer to sf_si */ ++ abi_ulong sf_ucontext; /* points to sf_uc */ ++ abi_ulong sf_addr; /* undocumented 4th arg */ ++ target_ucontext_t sf_uc; /* = *sf_uncontext */ ++ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/ ++ uint32_t __spare__[2]; ++}; ++ ++ ++/* Get the stack pointer. */ ++static inline abi_ulong ++get_sp_from_cpustate(CPUMIPSState *state) + { + return state->active_tc.gpr[29]; + } + ++/* ++ * Compare to mips/mips/pm_machdep.c sendsig() ++ * Assumes that "frame" memory is locked. ++ */ ++static inline int ++set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame, ++ abi_ulong frame_addr, struct target_sigaction *ka) ++{ ++ ++ frame->sf_signum = sig; ++ frame->sf_siginfo = 0; ++ frame->sf_ucontext = 0; ++ ++ frame->sf_si.si_signo = sig; ++ frame->sf_si.si_code = TARGET_SA_SIGINFO; ++ frame->sf_si.si_addr = regs->CP0_BadVAddr; ++ ++ /* ++ * Arguments to signal handler: ++ * a0 ($4) = signal number ++ * a1 ($5) = siginfo pointer ++ * a2 ($6) = ucontext pointer ++ * PC = signal handler pointer ++ * t9 ($25) = signal handler pointer ++ * $29 = point to sigframe struct ++ * ra ($31) = sigtramp at base of user stack ++ */ ++ regs->active_tc.gpr[ 4] = sig; ++ regs->active_tc.gpr[ 5] = frame_addr + ++ offsetof(struct target_sigframe, sf_si); ++ regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler; ++ regs->active_tc.gpr[29] = frame_addr; ++ regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE; ++ ++ return (0); ++} ++ ++/* ++ * Compare to mips/mips/pm_machdep.c get_mcontext() ++ * Assumes that the memory is locked if mcp points to user memory. ++ */ ++static inline int ++get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags) ++{ ++ int i, err = 0; ++ ++ if (flags & TARGET_MC_ADD_MAGIC) { ++ mcp->mc_regs[0] = tswapal(TARGET_UCONTEXT_MAGIC); ++ } else { ++ mcp->mc_regs[0] = 0; ++ } ++ ++ if (flags & TARGET_MC_SET_ONSTACK) { ++ mcp->mc_onstack = tswapal(1); ++ } else { ++ mcp->mc_onstack = 0; ++ } ++ ++ for(i = 1; i < 32; i++) ++ mcp->mc_regs[i] = tswapal(regs->active_tc.gpr[i]); ++ ++#if 0 /* XXX FP is not used right now. */ ++ abi_ulong used_fp = used_math() ? TARGET_MDTD_FPUSED : 0; ++ ++ mcp->mc_fpused = used_fp; ++ if (used_fp) { ++ preempt_disable(); ++ if (!is_fpu_owner()) { ++ own_fpu(); ++ for(i = 0; i < 33; i++) ++ mcp->mc_fpregs[i] = tswapal(regs->active_fpu.fpr[i]); ++ } ++ preempt_enable(); ++ } ++#else ++ mcp->mc_fpused = 0; ++#endif ++ ++ if (flags & TARGET_MC_GET_CLEAR_RET) { ++ mcp->mc_regs[2] = 0; /* v0 = 0 */ ++ mcp->mc_regs[3] = 0; /* v1 = 0 */ ++ mcp->mc_regs[7] = 0; /* a3 = 0 */ ++ } ++ ++ mcp->mc_pc = tswapal(regs->active_tc.PC); ++ mcp->mullo = tswapal(regs->active_tc.LO[0]); ++ mcp->mulhi = tswapal(regs->active_tc.HI[0]); ++ mcp->mc_tls = tswapal(regs->tls_value); ++ ++ /* Don't do any of the status and cause registers. */ ++ ++ return (err); ++} ++ ++/* Compare to mips/mips/pm_machdep.c set_mcontext() */ ++static inline int ++set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags) ++{ ++ int i, err = 0; ++ ++ for(i = 1; i < 32; i++) ++ regs->active_tc.gpr[i] = tswapal(mcp->mc_regs[i]); ++ ++#if 0 /* XXX FP is not used right now */ ++ abi_ulong used_fp = 0; ++ ++ used_fp = tswapal(mcp->mc_fpused) ++ conditional_used_math(used_fp); ++ ++ preempt_disabled(); ++ if (used_math()) { ++ /* restore fpu context if we have used it before */ ++ own_fpu(); ++ for (i = 0; i < 32; i++) ++ regs->active_fpu.fpr[i] = tswapal(mcp->mc_fpregs[i]); ++ } else { ++ /* Signal handler may have used FPU. Give it up. */ ++ lose_fpu(); ++ } ++ preempt_enable(); ++#endif ++ ++ regs->CP0_EPC = tswapal(mcp->mc_pc); ++ regs->active_tc.LO[0] = tswapal(mcp->mullo); ++ regs->active_tc.HI[0] = tswapal(mcp->mulhi); ++ regs->tls_value = tswapal(mcp->mc_tls); ++ ++ /* Don't do any of the status and cause registers. */ ++ ++ return (err); ++} ++ + #endif /* TARGET_SIGNAL_H */ +diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h +index d671f4e..e9c8a9f 100644 +--- a/bsd-user/mips64/target_signal.h ++++ b/bsd-user/mips64/target_signal.h +@@ -7,11 +7,186 @@ + #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) + #define TARGET_SZSIGCODE 16 + +-#define TARGET_UCONTEXT_MAGIC 0xACEDBADE ++struct target_sigcontext { ++ target_sigset_t sc_mask; /* signal mask to retstore */ ++ int32_t sc_onstack; /* sigstack state to restore */ ++ abi_long sc_pc; /* pc at time of signal */ ++ abi_long sc_reg[32]; /* processor regs 0 to 31 */ ++ abi_long mullo, mulhi; /* mullo and mulhi registers */ ++ int32_t sc_fpused; /* fp has been used */ ++ abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */ ++ abi_long sc_fpc_eir; /* fp exception instr reg */ ++ /* int32_t reserved[8]; */ ++}; + +-static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) ++typedef struct target_mcontext { ++ int32_t mc_onstack; /* sigstack state to restore */ ++ abi_long mc_pc; /* pc at time of signal */ ++ abi_long mc_regs[32]; /* process regs 0 to 31 */ ++ abi_long sr; /* status register */ ++ abi_long mullo, mulhi; ++ int32_t mc_fpused; /* fp has been used */ ++ abi_long mc_fpregs[33]; /* fp regs 0 to 32 & csr */ ++ abi_long mc_fpc_eir; /* fp exception instr reg */ ++ abi_ulong mc_tls; /* pointer to TLS area */ ++} target_mcontext_t; ++ ++typedef struct target_ucontext { ++ target_sigset_t uc_sigmask; ++ target_mcontext_t uc_mcontext; ++ abi_ulong uc_link; ++ target_stack_t uc_stack; ++ int32_t uc_flags; ++ int32_t __spare__[4]; ++} target_ucontext_t; ++ ++struct target_sigframe { ++ abi_ulong sf_signum; ++ abi_ulong sf_siginfo; /* code or pointer to sf_si */ ++ abi_ulong sf_ucontext; /* points to sf_uc */ ++ abi_ulong sf_addr; /* undocumented 4th arg */ ++ target_ucontext_t sf_uc; /* = *sf_uncontext */ ++ target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/ ++ uint32_t __spare__[2]; ++}; ++ ++static inline abi_ulong ++get_sp_from_cpustate(CPUMIPSState *state) + { + return state->active_tc.gpr[29]; + } + ++/* ++ * Compare to mips/mips/pm_machdep.c sendsig() ++ * Assumes that "frame" memory is locked. ++ */ ++static inline int ++set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame, ++ abi_ulong frame_addr, struct target_sigaction *ka) ++{ ++ ++ frame->sf_signum = sig; ++ frame->sf_siginfo = 0; ++ frame->sf_ucontext = 0; ++ ++ frame->sf_si.si_signo = sig; ++ frame->sf_si.si_code = TARGET_SA_SIGINFO; ++ frame->sf_si.si_addr = regs->CP0_BadVAddr; ++ ++ /* ++ * Arguments to signal handler: ++ * a0 ($4) = signal number ++ * a1 ($5) = siginfo pointer ++ * a2 ($6) = ucontext pointer ++ * PC = signal handler pointer ++ * t9 ($25) = signal handler pointer ++ * $29 = point to sigframe struct ++ * ra ($31) = sigtramp at base of user stack ++ */ ++ regs->active_tc.gpr[ 4] = sig; ++ regs->active_tc.gpr[ 5] = frame_addr + ++ offsetof(struct target_sigframe, sf_si); ++ regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler; ++ regs->active_tc.gpr[29] = frame_addr; ++ regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE; ++ ++ return (0); ++} ++ ++/* ++ * Compare to mips/mips/pm_machdep.c get_mcontext() ++ * Assumes that the memory is locked if mcp points to user memory. ++ */ ++static inline int ++get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags) ++{ ++ int i, err = 0; ++ ++ if (flags & TARGET_MC_ADD_MAGIC) { ++ mcp->mc_regs[0] = tswapal(TARGET_UCONTEXT_MAGIC); ++ } else { ++ mcp->mc_regs[0] = 0; ++ } ++ ++ if (flags & TARGET_MC_SET_ONSTACK) { ++ mcp->mc_onstack = tswapal(1); ++ } else { ++ mcp->mc_onstack = 0; ++ } ++ ++ for(i = 1; i < 32; i++) ++ mcp->mc_regs[i] = tswapal(regs->active_tc.gpr[i]); ++ ++#if 0 /* XXX FP is not used right now */ ++ abi_ulong used_fp = used_math() ? TARGET_MDTD_FPUSED : 0; ++ ++ mcp->mc_fpused = used_fp; ++ if (used_fp) { ++ preempt_disable(); ++ if (!is_fpu_owner()) { ++ own_fpu(); ++ for(i = 0; i < 33; i++) ++ mcp->mc_fpregs[i] = tswapal(regs->active_fpu.fpr[i]); ++ } ++ preempt_enable(); ++ } ++#else ++ mcp->mc_fpused = 0; ++#endif ++ ++ if (flags & TARGET_MC_GET_CLEAR_RET) { ++ mcp->mc_regs[2] = 0; /* v0 = 0 */ ++ mcp->mc_regs[3] = 0; /* v1 = 0 */ ++ mcp->mc_regs[7] = 0; /* a3 = 0 */ ++ } ++ ++ mcp->mc_pc = tswapal(regs->active_tc.PC); ++ mcp->mullo = tswapal(regs->active_tc.LO[0]); ++ mcp->mulhi = tswapal(regs->active_tc.HI[0]); ++ mcp->mc_tls = tswapal(regs->tls_value); ++ ++ /* Don't do any of the status and cause registers. */ ++ ++ return (err); ++} ++ ++/* Compare to mips/mips/pm_machdep.c set_mcontext() */ ++static inline int ++set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags) ++{ ++ int i, err = 0; ++ ++ for(i = 1; i < 32; i++) ++ regs->active_tc.gpr[i] = tswapal(mcp->mc_regs[i]); ++ ++#if 0 /* XXX FP is not used right now */ ++ abi_ulong used_fp = 0; ++ ++ used_fp = tswapal(mcp->mc_fpused) ++ conditional_used_math(used_fp); ++ ++ preempt_disabled(); ++ if (used_math()) { ++ /* restore fpu context if we have used it before */ ++ own_fpu(); ++ for (i = 0; i < 32; i++) ++ regs->active_fpu.fpr[i] = tswapal(mcp->mc_fpregs[i]); ++ } else { ++ /* Signal handler may have used FPU. Give it up. */ ++ lose_fpu(); ++ } ++ preempt_enable(); ++#endif ++ ++ regs->CP0_EPC = tswapal(mcp->mc_pc); ++ regs->active_tc.LO[0] = tswapal(mcp->mullo); ++ regs->active_tc.HI[0] = tswapal(mcp->mulhi); ++ regs->tls_value = tswapal(mcp->mc_tls); ++ ++ /* Don't do any of the status and cause registers. */ ++ ++ return (err); ++} ++ + #endif /* TARGET_SIGNAL_H */ ++ +diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c +--- a/bsd-user/mmap.c ++++ b/bsd-user/mmap.c +@@ -74,6 +74,8 @@ void mmap_unlock(void) + } + #endif + ++#if 0 /* XXX not sure why we need our own g_malloc() and friends. ++ g_strdup(), however, has serious problems with this g_malloc/g_free */ + static void *bsd_vmalloc(size_t size) + { + void *p; +@@ -133,6 +135,7 @@ void *g_realloc(void *ptr, size_t size) + g_free(ptr); + return new_ptr; + } ++#endif + + /* NOTE: all the constants are the HOST ones, but addresses are target. */ + int target_mprotect(abi_ulong start, abi_ulong len, int prot) +diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h +index ab7e18c..9d4edbf 100644 +--- a/bsd-user/qemu.h ++++ b/bsd-user/qemu.h +@@ -80,7 +80,7 @@ struct emulated_sigtable { + typedef struct TaskState { + struct TaskState *next; + int used; /* non zero if used */ +-#if 1 ++ long ts_tid; /* tid (or pid) of this task */ + #ifdef TARGET_ARM + int swi_errno; + #endif +@@ -90,7 +90,6 @@ typedef struct TaskState { + uint32_t heap_limit; + #endif + uint32_t stack_base; +-#endif + struct image_info *info; + struct bsd_binprm *bprm; + +diff --git a/bsd-user/signal.c b/bsd-user/signal.c +index 52441c4..d56837b 100644 +--- a/bsd-user/signal.c ++++ b/bsd-user/signal.c +@@ -31,7 +31,7 @@ + #include "qemu.h" + #include "target_signal.h" + +-//#define DEBUG_SIGNAL ++// #define DEBUG_SIGNAL + + #ifndef _NSIG + #define _NSIG 128 +@@ -606,101 +606,31 @@ do_sigaction(int sig, const struct target_sigaction *act, + return (ret); + } + +-#if defined(TARGET_MIPS64) +-static inline int +-restore_sigmcontext(CPUMIPSState *regs, target_mcontext_t *mc) +-{ +- int i, err = 0; +- +- for(i = 1; i < 32; i++) +- err |= __get_user(regs->active_tc.gpr[i], +- &mc->mc_regs[i]); +- err |= __get_user(regs->CP0_EPC, &mc->mc_pc); +- err |= __get_user(regs->active_tc.LO[0], &mc->mullo); +- err |= __get_user(regs->active_tc.HI[0], &mc->mulhi); +- err |= __get_user(regs->tls_value, &mc->mc_tls); /* XXX thread tls */ +- +-#if 0 /* XXX */ +- int used_fp = 0; +- +- err |= __get_user(used_fp, &mc->mc_fpused); +- conditional_used_math(used_fp); +- +- preempt_disabled(); +- if (used_math()) { +- /* restore fpu context if we have used it before */ +- own_fpu(); +- err |= restore_fp_context(mc); +- } else { +- /* signal handler may have used FPU. Give it up. */ +- lose_fpu(); +- } +- preempt_enable(); +-#endif +- +- return (err); +-} +- +-static inline int +-setup_sigmcontext(CPUMIPSState *regs, target_mcontext_t *mc, int32_t oonstack) +-{ +- int i, err = 0; +- abi_long ucontext_magic = TARGET_UCONTEXT_MAGIC; +- +- err = __put_user(oonstack ? 1 : 0, &mc->mc_onstack); +- err |= __put_user(regs->active_tc.PC, &mc->mc_pc); +- err |= __put_user(regs->active_tc.LO[0], &mc->mullo); +- err |= __put_user(regs->active_tc.HI[0], &mc->mulhi); +- err |= __put_user(regs->tls_value, &mc->mc_tls); /* XXX thread tls */ +- +- err |= __put_user(ucontext_magic, &mc->mc_regs[0]); +- for(i = 1; i < 32; i++) +- err |= __put_user(regs->active_tc.gpr[i], &mc->mc_regs[i]); +- +- err |= __put_user(0, &mc->mc_fpused); +- +-#if 0 /* XXX */ +- err |= __put_user(used_math(), &mc->mc_fpused); +- if (used_math()) +- goto out; +- +- /* +- * Save FPU state to signal context. Signal handler will "inherit" +- * current FPU state. +- */ +- preempt_disable(); +- +- if (!is_fpu_owner()) { +- own_fpu(); +- for(i = 0; i < 33; i++) +- err |= __put_user(regs->active_tc.fpregs[i], &mc->mc_fpregs[i]); +- } +- err |= save_fp_context(fg); +- +- preempt_enable(); +-out: +-#endif +- return (err); +-} ++#if defined(TARGET_MIPS) || defined(TARGET_SPARC64) + + static inline abi_ulong +-get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size) ++get_sigframe(struct target_sigaction *ka, CPUArchState *regs, size_t frame_size) + { + abi_ulong sp; + + /* Use default user stack */ +- sp = regs->active_tc.gpr[29]; ++ sp = get_sp_from_cpustate(regs); + + if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) { +- sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; ++ sp = target_sigaltstack_used.ss_sp + ++ target_sigaltstack_used.ss_size; + } + ++#if defined(TARGET_MIPS) + return ((sp - frame_size) & ~7); ++#else ++ return (sp - frame_size); ++#endif + } + +-/* compare to mips/mips/pm_machdep.c sendsig() */ ++/* compare to mips/mips/pm_machdep.c and sparc64/sparc64/machdep.c sendsig() */ + static void setup_frame(int sig, struct target_sigaction *ka, +- target_sigset_t *set, CPUMIPSState *regs) ++ target_sigset_t *set, CPUArchState *regs) + { + struct target_sigframe *frame; + abi_ulong frame_addr; +@@ -709,54 +639,36 @@ static void setup_frame(int sig, struct target_sigaction *ka, + #ifdef DEBUG_SIGNAL + fprintf(stderr, "setup_frame()\n"); + #endif ++#if defined(TARGET_SPARC64) ++ if (!sparc_user_sigtramp) { ++ /* No signal trampoline... kill the process. */ ++ fprintf(stderr, "setup_frame(): no sigtramp\n"); ++ force_sig(TARGET_SIGKILL); ++ } ++#endif + + frame_addr = get_sigframe(ka, regs, sizeof(*frame)); + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) + goto give_sigsegv; + +- if (setup_sigmcontext(regs, &frame->sf_uc.uc_mcontext, +- ! on_sig_stack(frame_addr))) ++#if defined(TARGET_MIPS) ++ int mflags = on_sig_stack(frame_addr) ? TARGET_MC_ADD_MAGIC : ++ TARGET_MC_SET_ONSTACK | TARGET_MC_ADD_MAGIC; ++#else ++ int mflags = 0; ++#endif ++ if (get_mcontext(regs, &frame->sf_uc.uc_mcontext, mflags)) + goto give_sigsegv; + + for(i = 0; i < TARGET_NSIG_WORDS; i++) { +- if (__put_user(set->__bits[i], &frame->sf_uc.uc_sigmask.__bits[i])) ++ if (__put_user(set->__bits[i], ++ &frame->sf_uc.uc_sigmask.__bits[i])) + goto give_sigsegv; + } + +- /* fill in sigframe structure */ +- if (__put_user(sig, &frame->sf_signum)) +- goto give_sigsegv; +- if (__put_user(0, &frame->sf_siginfo)) +- goto give_sigsegv; +- if (__put_user(0, &frame->sf_ucontext)) ++ if (set_sigtramp_args(regs, sig, frame, frame_addr, ka)) + goto give_sigsegv; + +- /* fill in siginfo structure */ +- if (__put_user(sig, &frame->sf_si.si_signo)) +- goto give_sigsegv; +- if (__put_user(TARGET_SA_SIGINFO, &frame->sf_si.si_code)) +- goto give_sigsegv; +- if (__put_user(regs->CP0_BadVAddr, &frame->sf_si.si_addr)) +- goto give_sigsegv; +- +- /* +- * Arguments to signal handler: +- * a0 ($4) = signal number +- * a1 ($5) = siginfo pointer +- * a2 ($6) = ucontext pointer +- * PC = signal handler pointer +- * t9 ($25) = signal handler pointer +- * $29 = point to sigframe struct +- * ra ($31) = sigtramp at base of user stack +- */ +- regs->active_tc.gpr[ 4] = sig; +- regs->active_tc.gpr[ 5] = frame_addr + +- offsetof(struct target_sigframe, sf_si); +- regs->active_tc.gpr[ 6] = frame_addr + +- offsetof(struct target_sigframe, sf_uc); +- regs->active_tc.gpr[25] = regs->active_tc.PC = ka->_sa_handler; +- regs->active_tc.gpr[29] = frame_addr; +- regs->active_tc.gpr[31] = TARGET_PS_STRINGS - TARGET_SZSIGCODE; + unlock_user_struct(frame, frame_addr, 1); + return; + +@@ -766,7 +678,7 @@ give_sigsegv: + } + + long +-do_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr) ++do_sigreturn(CPUArchState *regs, abi_ulong uc_addr) + { + target_ucontext_t *ucontext; + sigset_t blocked; +@@ -784,14 +696,17 @@ do_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr) + goto badframe; + } + +- if (restore_sigmcontext(regs, &ucontext->uc_mcontext)) ++ if (set_mcontext(regs, &ucontext->uc_mcontext, 0)) + goto badframe; + + target_to_host_sigset_internal(&blocked, &target_set); + sigprocmask(SIG_SETMASK, &blocked, NULL); + +- regs->active_tc.PC = regs->CP0_EPC; +- regs->CP0_EPC = 0; /* XXX for nested signals ? */ ++#if defined(TARGET_MIPS) ++ CPUMIPSState *mips_regs = (CPUMIPSState *)regs; ++ mips_regs->active_tc.PC = mips_regs->CP0_EPC; ++ mips_regs->CP0_EPC = 0; /* XXX for nested signals ? */ ++#endif + return (-TARGET_QEMU_ESIGRETURN); + + badframe: +@@ -799,9 +714,10 @@ badframe: + return (0); + } + +-#elif defined(TARGET_SPARC64) + +-extern abi_ulong sparc_user_sigtramp; ++ ++/* #elif defined(TARGET_SPARC64) */ ++#if 0 + + #define mc_flags mc_global[0] + #define mc_sp mc_out[6] +@@ -1039,6 +955,7 @@ badframe: + force_sig(TARGET_SIGSEGV); + return (0); + } ++#endif + + #else + +diff --git a/bsd-user/sparc/target_signal.h b/bsd-user/sparc/target_signal.h +index 79dfc1e..e2fe79c 100644 +--- a/bsd-user/sparc/target_signal.h ++++ b/bsd-user/sparc/target_signal.h +@@ -13,9 +13,34 @@ + #define TARGET_MINSIGSTKSZ (512 * 4) + #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) + ++typedef target_ulong target_mcontext_t; /* dummy */ ++ ++typedef struct target_ucontext { ++ target_sigset_t uc_sigmask; ++ target_mcontext_t uc_mcontext; ++ abi_ulong uc_link; ++ target_stack_t uc_stack; ++ int32_t uc_flags; ++ int32_t __spare__[4]; ++} target_ucontext_t; ++ + static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state) + { + return state->regwptr[UREG_FP]; + } + ++static inline int ++get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags) ++{ ++ fprintf(stderr, "SPARC doesn't have support for get_mcontext()\n"); ++ return (-TARGET_ENOSYS); ++} ++ ++static inline int ++set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags) ++{ ++ fprintf(stderr, "SPARC doesn't have support for set_mcontext()\n"); ++ return (-TARGET_ENOSYS); ++} ++ + #endif /* TARGET_SIGNAL_H */ +diff --git a/bsd-user/sparc64/target_signal.h b/bsd-user/sparc64/target_signal.h +index d3e58bb..1bc7c96 100644 +--- a/bsd-user/sparc64/target_signal.h ++++ b/bsd-user/sparc64/target_signal.h +@@ -10,12 +10,239 @@ + #define UREG_FP UREG_I6 + #endif + ++#define mc_flags mc_global[0] ++#define mc_sp mc_out[6] ++#define mc_fprs mc_local[0] ++#define mc_fsr mc_local[1] ++#define mc_gsr mc_local[2] ++#define mc_tnpc mc_in[0] ++#define mc_tpc mc_in[1] ++#define mc_tstate mc_in[2] ++#define mc_y mc_in[4] ++#define mc_wstate mc_in[5] ++ ++#define ureg_i0 regwptr[0 ] ++#define ureg_i1 regwptr[1 ] ++#define ureg_i2 regwptr[2 ] ++#define ureg_i3 regwptr[3 ] ++#define ureg_i4 regwptr[4 ] ++#define ureg_i5 regwptr[5 ] ++#define ureg_i6 regwptr[6 ] ++#define ureg_i7 regwptr[7 ] ++#define ureg_l0 regwptr[8 ] ++#define ureg_l1 regwptr[9 ] ++#define ureg_l2 regwptr[10] ++#define ureg_l3 regwptr[11] ++#define ureg_l4 regwptr[12] ++#define ureg_l5 regwptr[13] ++#define ureg_l6 regwptr[14] ++#define ureg_l7 regwptr[15] ++#define ureg_o0 regwptr[16] ++#define ureg_o1 regwptr[17] ++#define ureg_o2 regwptr[18] ++#define ureg_o3 regwptr[19] ++#define ureg_o4 regwptr[20] ++#define ureg_o5 regwptr[21] ++#define ureg_o6 regwptr[22] ++#define ureg_o7 regwptr[23] ++#define ureg_fp ureg_i6 ++#define ureg_sp ureg_o6 ++#define ureg_fprs fprs ++#define ureg_fsr fsr ++#define ureg_gsr gsr ++#define ureg_tnpc npc ++#define ureg_tpc pc ++#define ureg_y y ++ ++#define TARGET_FPRS_FEF (1 << 2) ++#define TARGET_MC_VERSION 1L ++ + #define TARGET_MINSIGSTKSZ (1024 * 4) + #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) + +-static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state) ++#define TARGET_STACK_BIAS 2047 /* AKA. SPOFF */ ++ ++struct target_mcontext { ++ uint64_t mc_global[8]; ++ uint64_t mc_out[8]; ++ uint64_t mc_local[8]; ++ uint64_t mc_in[8]; ++ uint32_t mc_fp[64]; ++} __aligned(64); ++ ++typedef struct target_mcontext target_mcontext_t; ++ ++typedef struct target_ucontext { ++ target_sigset_t uc_sigmask; ++ target_mcontext_t uc_mcontext; ++ abi_ulong uc_link; ++ target_stack_t uc_stack; ++ int32_t uc_flags; ++ int32_t __spare__[4]; ++} target_ucontext_t; ++ ++struct target_sigframe { ++ target_ucontext_t sf_uc; ++ target_siginfo_t sf_si; ++}; ++ ++extern abi_ulong sparc_user_sigtramp; ++ ++static inline int ++set_sigtramp_args(CPUSPARCState *regs, int sig, struct target_sigframe *frame, ++ abi_ulong frame_addr, struct target_sigaction *ka) + { ++ ++ frame->sf_si.si_signo = sig; ++ frame->sf_si.si_code = TARGET_SA_SIGINFO; ++ ++ /* Arguments to signal handler: ++ * ++ * i0 = signal number ++ * i1 = pointer to siginfo struct ++ * i2 = pointer to ucontext struct ++ * i3 = (not used in new style) ++ * i4 = signal handler address (called by sigtramp) ++ */ ++ regs->ureg_i0 = sig; ++ regs->ureg_i1 = frame_addr + ++ offsetof(struct target_sigframe, sf_si); ++ regs->ureg_i2 = frame_addr + ++ offsetof(struct target_sigframe, sf_uc); ++ /* env->ureg_o3 used in the Old FreeBSD-style arguments. */ ++ regs->ureg_i4 = ka->_sa_handler; ++ regs->ureg_tpc = sparc_user_sigtramp; ++ regs->ureg_tnpc = (regs->ureg_tpc + 4); ++ regs->ureg_sp = frame_addr - TARGET_STACK_BIAS; ++ ++ return (0); ++} ++ ++static inline abi_ulong ++get_sp_from_cpustate(CPUSPARCState *state) ++{ ++ + return state->regwptr[UREG_FP]; + } + ++/* compare to sparc64/sparc64/machdep.c get_mcontext() */ ++static inline int ++get_mcontext(CPUSPARCState *regs, target_mcontext_t *mcp, int flags) ++{ ++ ++ /* Skip over the trap instruction, first. */ ++ regs->pc = regs->npc; ++ regs->npc += 4; ++ ++ mcp->mc_flags = TARGET_MC_VERSION; /* mc_global[0] */ ++ mcp->mc_global[1] = tswapal(regs->gregs[1]); ++ mcp->mc_global[2] = tswapal(regs->gregs[2]); ++ mcp->mc_global[3] = tswapal(regs->gregs[3]); ++ mcp->mc_global[4] = tswapal(regs->gregs[4]); ++ mcp->mc_global[5] = tswapal(regs->gregs[5]); ++ mcp->mc_global[6] = tswapal(regs->gregs[6]); ++ /* skip %g7 since it is used as the userland TLS register */ ++ ++ if (flags & TARGET_MC_GET_CLEAR_RET) { ++ mcp->mc_out[0] = 0; ++ mcp->mc_out[1] = 0; ++ } else { ++ mcp->mc_out[0] = tswapal(regs->ureg_i0); ++ mcp->mc_out[1] = tswapal(regs->ureg_i1); ++ } ++ mcp->mc_out[2] = tswapal(regs->ureg_i2); ++ mcp->mc_out[3] = tswapal(regs->ureg_i3); ++ mcp->mc_out[4] = tswapal(regs->ureg_i4); ++ mcp->mc_out[5] = tswapal(regs->ureg_i5); ++ mcp->mc_out[6] = tswapal(regs->ureg_i6); ++ mcp->mc_out[7] = tswapal(regs->ureg_i7); ++ ++ mcp->mc_fprs = tswapal(regs->fprs); /* mc_local[0] */ ++ mcp->mc_fsr = tswapal(regs->fsr); /* mc_local[1] */ ++ mcp->mc_gsr = tswapal(regs->gsr); /* mc_local[2] */ ++ ++ mcp->mc_tnpc = tswapal(regs->npc); /* mc_in[0] */ ++ mcp->mc_tpc = tswapal(regs->pc); /* mc_in[1] */ ++#if 0 ++ mcp->mc_tstate = tswapal(regs->ureg_tstate); /* mc_in[2] */ ++#else ++ abi_ulong cwp64 = cpu_get_cwp64(regs); ++ abi_ulong ccr = cpu_get_ccr(regs) << 32; ++ abi_ulong asi = (regs->asi & 0xff) << 24; ++ mcp->mc_tstate = tswapal(ccr | asi | cwp64); ++#endif ++ ++ mcp->mc_y = tswapal(regs->y); /* mc_in[4] */ ++ ++ /* XXX ++ if ((regs->ureg_l0 & TARGET_FPRS_FEF) != 0) { ++ int i; ++ ++ for(i = 0; i < 64; i++) ++ mcp->mc_fp[i] = tswapal(regs->fpr[i]); ++ } ++ */ ++ ++ return (0); ++} ++ ++extern void helper_flushw(CPUSPARCState *env); ++ ++/* compare to sparc64/sparc64/machdep.c set_mcontext() */ ++static inline int ++set_mcontext(CPUSPARCState *regs, target_mcontext_t *mcp, int flags) ++{ ++ /* XXX need to add version check here. */ ++ ++ /* Make sure the windows are spilled first. */ ++ helper_flushw(regs); ++ ++ regs->gregs[1] = tswapal(mcp->mc_global[1]); ++ regs->gregs[2] = tswapal(mcp->mc_global[2]); ++ regs->gregs[3] = tswapal(mcp->mc_global[3]); ++ regs->gregs[4] = tswapal(mcp->mc_global[4]); ++ regs->gregs[5] = tswapal(mcp->mc_global[5]); ++ regs->gregs[6] = tswapal(mcp->mc_global[6]); ++ ++ regs->ureg_i0 = tswapal(mcp->mc_out[0]); ++ regs->ureg_i1 = tswapal(mcp->mc_out[1]); ++ regs->ureg_i2 = tswapal(mcp->mc_out[2]); ++ regs->ureg_i3 = tswapal(mcp->mc_out[3]); ++ regs->ureg_i4 = tswapal(mcp->mc_out[4]); ++ regs->ureg_i5 = tswapal(mcp->mc_out[5]); ++ regs->ureg_i6 = tswapal(mcp->mc_out[6]); ++ regs->ureg_i7 = tswapal(mcp->mc_out[7]); ++ ++ regs->fprs = tswapal(mcp->mc_fprs); /* mc_local[0] */ ++ regs->fsr = tswapal(mcp->mc_fsr); /* mc_local[1] */ ++ regs->gsr = tswapal(mcp->mc_gsr); /* mc_local[2] */ ++ ++ regs->npc = tswapal(mcp->mc_tnpc); /* mc_in[0] */ ++ regs->pc = tswapal(mcp->mc_tpc); /* mc_in[1] */ ++ ++#if 0 ++ regs->ureg_tstate = tswapal(mcp->mc_tstate); /* mc_in[2] */ ++#else ++ abi_ulong tstate = tswapal(mcp->mc_tstate); /* mc_in[2] */ ++ ++ regs->asi = (tstate >> 24) & 0xff; ++ cpu_put_ccr(regs, tstate >> 32); ++ cpu_put_cwp64(regs, tstate & 0x1f); ++ ++#endif ++ regs->ureg_y = tswapal(mcp->mc_y); /* mc_in[4] */ ++ ++ /* XXX ++ if ((regs->ureg_fprs & TARGET_FPRS_FEF) != 0) { ++ int i; ++ ++ regs->ureg_l0 = 0; ++ for(i = 0; i < 64; i++) ++ regs->fpr[i] = tswapal(mcp->mc_fp[i]); ++ } ++ */ ++ ++ return (0); ++} ++ + #endif /* TARGET_SIGNAL_H */ +diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c +index 625c3cf..4deb0db 100644 +--- a/bsd-user/syscall.c ++++ b/bsd-user/syscall.c +@@ -43,6 +43,12 @@ + #ifdef __FreeBSD__ + #include <sys/regression.h> + #include <sys/procdesc.h> ++#include <sys/ucontext.h> ++#include <sys/thr.h> ++#include <sys/rtprio.h> ++#include <sys/umtx.h> ++#include <pthread.h> ++#include <machine/atomic.h> + #endif + #include <sys/un.h> + #include <sys/ipc.h> +@@ -251,7 +257,24 @@ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms) + #ifdef TARGET_MIPS + static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms) + { +- return -TARGET_EINVAL; ++ int ret = 0; ++ CPUMIPSState *mips_env = (CPUMIPSState *)env; ++ ++ switch(op) { ++ case TARGET_MIPS_SET_TLS: ++ if (get_user(mips_env->tls_value, parms, abi_ulong)) ++ ret = -TARGET_EFAULT; ++ break; ++ case TARGET_MIPS_GET_TLS: ++ if (put_user(mips_env->tls_value, parms, abi_ulong)) ++ ret = -TARGET_EFAULT; ++ break; ++ default: ++ ret = -TARGET_EINVAL; ++ break; ++ } ++ ++ return (ret); + } + #endif + +@@ -2119,6 +2142,383 @@ do_fork(CPUArchState *env, int num, int flags, int *fdp) + return (ret); + } + ++#if defined(CONFIG_USE_NPTL) ++ ++#define NEW_STACK_SIZE (0x40000) ++ ++static pthread_mutex_t new_thread_lock = PTHREAD_MUTEX_INITIALIZER; ++typedef struct { ++ CPUArchState *env; ++ long tid; ++ pthread_mutex_t mutex; ++ pthread_cond_t cond; ++ pthread_t thread; ++ sigset_t sigmask; ++ struct target_thr_param param; ++} new_thread_info_t; ++ ++static void * ++new_thread_start(void *arg) ++{ ++ new_thread_info_t *info = arg; ++ CPUArchState *env; ++ TaskState *ts; ++ long tid; ++ ++ env = info->env; ++ thread_env = env; ++ ts = (TaskState *)thread_env->opaque; ++ (void)thr_self(&tid); ++ info->tid = tid; ++ task_settid(ts); ++ ++ /* copy out the TID info */ ++ if (info->param.child_tid) ++ put_user(tid, info->param.child_tid, abi_long); ++ if (info->param.parent_tid) ++ put_user(tid, info->param.parent_tid, abi_long); ++ ++#ifdef TARGET_MIPS64 ++ CPUMIPSState *regs = env; ++ regs->active_tc.gpr[25] = regs->active_tc.PC = info->param.start_func; ++ regs->active_tc.gpr[ 4] = info->param.arg; ++ regs->active_tc.gpr[29] = info->param.stack_base; ++#endif ++ /* Eenable signals */ ++ sigprocmask(SIG_SETMASK, &info->sigmask, NULL); ++ /* Signal to the parent that we're ready. */ ++ pthread_mutex_lock(&info->mutex); ++ pthread_cond_broadcast(&info->cond); ++ pthread_mutex_unlock(&info->mutex); ++ /* Wait until the parent has finished initializing the TLS state. */ ++ pthread_mutex_lock(&new_thread_lock); ++ pthread_mutex_unlock(&new_thread_lock); ++ ++ cpu_loop(env); ++ /* never exits */ ++ ++ return (NULL); ++} ++ ++static void ++rtp_to_schedparam(const struct rtprio *rtp, int *policy, struct sched_param *param) ++{ ++ ++ switch(rtp->type) { ++ case RTP_PRIO_REALTIME: ++ *policy = SCHED_RR; ++ param->sched_priority = RTP_PRIO_MAX - rtp->prio; ++ break; ++ ++ case RTP_PRIO_FIFO: ++ *policy = SCHED_FIFO; ++ param->sched_priority = RTP_PRIO_MAX - rtp->prio; ++ break; ++ ++ default: ++ *policy = SCHED_OTHER; ++ param->sched_priority = 0; ++ break; ++ } ++} ++ ++static int ++do_thr_create(CPUArchState *env, ucontext_t *ctx, long *id, int flags) ++{ ++ ++ return (unimplemented(TARGET_FREEBSD_NR_thr_create)); ++} ++ ++static int ++do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size) ++{ ++ new_thread_info_t info; ++ pthread_attr_t attr; ++ TaskState *ts; ++ CPUArchState *new_env; ++ struct target_thr_param *target_param; ++ abi_ulong target_rtp_addr; ++ struct target_rtprio *target_rtp; ++ struct rtprio *rtp_ptr, rtp; ++ TaskState *parent_ts = (TaskState *)env->opaque; ++ sigset_t sigmask; ++ struct sched_param sched_param; ++ int sched_policy; ++ int ret = 0; ++ ++ memset(&info, 0, sizeof(info)); ++ ++ if (!lock_user_struct(VERIFY_READ, target_param, target_param_addr, 1)) ++ return (-TARGET_EFAULT); ++ info.param.start_func = tswapal(target_param->start_func); ++ info.param.arg = tswapal(target_param->arg); ++ info.param.stack_base = tswapal(target_param->stack_base); ++ info.param.stack_size = tswapal(target_param->stack_size); ++ info.param.tls_base = tswapal(target_param->tls_base); ++ info.param.tls_size = tswapal(target_param->tls_size); ++ info.param.child_tid = tswapal(target_param->child_tid); ++ info.param.parent_tid = tswapal(target_param->parent_tid); ++ target_rtp_addr = info.param.rtp = tswapal(target_param->rtp); ++ unlock_user(target_param, target_param_addr, 0); ++ ++ if (target_rtp_addr) { ++ if (!lock_user_struct(VERIFY_READ, target_rtp, target_rtp_addr, ++ 1)) ++ return (-TARGET_EFAULT); ++ rtp.type = tswap16(target_rtp->type); ++ rtp.prio = tswap16(target_rtp->prio); ++ unlock_user(target_rtp, target_rtp_addr, 0); ++ rtp_ptr = &rtp; ++ } else { ++ rtp_ptr = NULL; ++ } ++ ++ /* Create a new CPU instance. */ ++ ts = g_malloc0(sizeof(TaskState)); ++ init_task_state(ts); ++ new_env = cpu_copy(env); ++#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC) ++ cpu_reset(ENV_GET_CPU(new_env)); ++#endif ++ ++ /* init regs that differ from the parent thread. */ ++ cpu_clone_regs(new_env, info.param.stack_base); ++ new_env->opaque = ts; ++ ts->bprm = parent_ts->bprm; ++ ts->info = parent_ts->info; ++ ++#if defined(TARGET_MIPS) ++ env->tls_value = info.param.tls_base; ++ /* cpu_set_tls(new_env, info.param.tls_base); */ ++#endif ++ ++ /* Grab a mutex so that thread setup appears atomic. */ ++ pthread_mutex_lock(&new_thread_lock); ++ ++ pthread_mutex_init(&info.mutex, NULL); ++ pthread_mutex_lock(&info.mutex); ++ pthread_cond_init(&info.cond, NULL); ++ info.env = new_env; ++ ++ /* XXX return value needs to be checked... */ ++ pthread_attr_init(&attr); ++ pthread_attr_setstacksize(&attr, NEW_STACK_SIZE); ++ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); ++ if (rtp_ptr) { ++ rtp_to_schedparam(&rtp, &sched_policy, &sched_param); ++ pthread_attr_setschedpolicy(&attr, sched_policy); ++ pthread_attr_setschedparam(&attr, &sched_param); ++ } ++ ++ /* ++ * It is not safe to deliver signals until the child has finished ++ * initializing, so temporarily block all signals. ++ */ ++ sigfillset(&sigmask); ++ sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask); ++ ++ /* XXX return value needs to be checked... */ ++ ret = pthread_create(&info.thread, &attr, new_thread_start, &info); ++ /* XXX Free new CPU state if thread creation fails. */ ++ ++ sigprocmask(SIG_SETMASK, &info.sigmask, NULL); ++ pthread_attr_destroy(&attr); ++ if (0 == ret) { ++ /* Wait for the child to initialize. */ ++ pthread_cond_wait(&info.cond, &info.mutex); ++ } else { ++ /* pthread_create failed. */ ++ } ++ ++ pthread_mutex_unlock(&info.mutex); ++ pthread_cond_destroy(&info.cond); ++ pthread_mutex_destroy(&info.mutex); ++ pthread_mutex_unlock(&new_thread_lock); ++ ++ return (ret); ++} ++ ++static int ++do_thr_self(long *id) ++{ ++ ++ return (get_errno(thr_self(id))); ++} ++ ++static void ++do_thr_exit(CPUArchState *cpu_env, abi_ulong tid_addr) ++{ ++ ++ if (first_cpu->next_cpu) { ++ TaskState *ts; ++ CPUArchState **lastp, *p; ++ ++ /* ++ * *XXX This probably breaks if a signal arrives. ++ * We should disable signals. ++ */ ++ cpu_list_lock(); ++ lastp = &first_cpu; ++ p = first_cpu; ++ while (p && p != (CPUArchState *)cpu_env) { ++ lastp = &p->next_cpu; ++ p = p->next_cpu; ++ } ++ /* ++ * if we didn't find the CPU for this thread then something ++ * is horribly wrong. ++ */ ++ if (!p) ++ abort(); ++ /* Remove the CPU from the list. */ ++ *lastp = p->next_cpu; ++ cpu_list_unlock(); ++ ts = ((CPUArchState *)cpu_env)->opaque; ++ ++ if (tid_addr) { ++ /* Signal target userland that it can free the stack. */ ++ if (! put_user_u32(1, tid_addr)) ++ _umtx_op(g2h(tid_addr), UMTX_OP_WAKE, INT_MAX, ++ NULL, NULL); ++ } ++ ++ thread_env = NULL; ++ object_delete(OBJECT(ENV_GET_CPU(cpu_env))); ++ g_free(ts); ++ pthread_exit(NULL); ++ } ++} ++ ++static int ++do_thr_kill(long id, int sig) ++{ ++ ++ return (get_errno(thr_kill(id, sig))); ++} ++ ++static int ++do_thr_kill2(pid_t pid, long id, int sig) ++{ ++ ++ return (get_errno(thr_kill2(pid, id, sig))); ++} ++ ++static int ++do_thr_suspend(const struct timespec *timeout) ++{ ++ ++ return (get_errno(thr_suspend(timeout))); ++} ++ ++static int ++do_thr_wake(long tid) ++{ ++ ++ return (get_errno(thr_wake(tid))); ++} ++ ++static int ++do_thr_set_name(long tid, char *name) ++{ ++ ++ return (get_errno(thr_set_name(tid, name))); ++} ++ ++ ++#else /* ! CONFIG_USE_NPTL */ ++ ++static int ++do_thr_create(CPUArchState *env, ucontext_t *ctx, long *id, int flags) ++{ ++ return (unimplemented(TARGET_FREEBSD_NR_thr_create)); ++} ++ ++static int ++do_thr_new(CPUArchState *env, abi_ulong target_param_addr, int32_t param_size) ++{ ++ return (unimplemented(TARGET_FREEBSD_NR_thr_new)); ++} ++ ++static int ++do_thr_self(long *tid) ++{ ++ return (unimplemented(TARGET_FREEBSD_NR_thr_self)); ++} ++ ++static void ++do_thr_exit(CPUArchState *cpu_env, abi_ulong state_addr) ++{ ++} ++ ++static int ++do_thr_kill(long tid, int sig) ++{ ++ return (unimplemented(TARGET_FREEBSD_NR_thr_kill2)); ++} ++ ++static int ++do_thr_kill2(pid_t pid, long tid, int sig) ++{ ++ return (unimplemented(TARGET_FREEBSD_NR_thr_kill2)); ++} ++ ++static int ++do_thr_suspend(const struct timespec *timeout) ++{ ++ return (unimplemented(TARGET_FREEBSD_NR_thr_suspend)); ++} ++ ++static int ++do_thr_wake(long tid) ++{ ++ return (unimplemented(TARGET_FREEBSD_NR_thr_wake)); ++} ++ ++static int ++do_thr_set_name(long tid, char *name) ++{ ++ return (unimplemented(TARGET_FREEBSD_NR_thr_set_name)); ++} ++ ++#endif /* CONFIG_USE_NPTL */ ++ ++static int ++do_umtx_lock(abi_ulong umtx_addr, uint32_t id) ++{ ++ int ret = 0; ++ ++ for (;;) { ++ ret = get_errno(_umtx_op(g2h(umtx_addr + ++ offsetof(struct target_umtx, u_owner)), ++ UMTX_OP_MUTEX_WAIT, UMTX_UNOWNED, 0, 0)); ++ if (ret) ++ return (ret); ++ if (atomic_cmpset_acq_32(g2h(umtx_addr + ++ offsetof(struct target_umtx, u_owner)), ++ UMTX_UNOWNED, id)) ++ return (0); ++ } ++} ++ ++static int ++do_umtx_unlock(abi_ulong umtx_addr, uint32 id) ++{ ++ uint32_t owner; ++ ++ do { ++ if (get_user_u32(owner, umtx_addr + ++ offsetof(struct target_umtx, u_owner))) ++ return (-TARGET_EFAULT); ++ if (owner != id) ++ return (-TARGET_EPERM); ++ } while (!atomic_cmpset_rel_32(g2h(umtx_addr + ++ offsetof(struct target_umtx, u_owner)), owner, ++ UMUTEX_UNOWNED)); ++ ++ return (0); ++} ++ ++ + /* do_syscall() should always have a single exit point at the end so + that actions, such as logging of syscall results, can be performed. + All errnos that do_syscall() returns must be -TARGET_<errcode>. */ +@@ -4091,6 +4491,23 @@ do_stat: + break; + #endif + ++#ifdef TARGET_FREEBSD_NR_getdomainname ++ case TARGET_FREEBSD_NR_getdomainname: ++ ret = unimplemented(num); ++ break; ++#endif ++#ifdef TARGET_FREEBSD_NR_setdomainname ++ case TARGET_FREEBSD_NR_setdomainname: ++ ret = unimplemented(num); ++ break; ++#endif ++#ifdef TARGET_FREEBSD_NR_uname ++ case TARGET_FREEBSD_NR_uname: ++ ret = unimplemented(num); ++ break; ++#endif ++ ++ + #if 0 /* XXX not supported in libc yet, it seems (10.0 addition). */ + case TARGET_FREEBSD_NR_posix_fadvise: + { +@@ -4136,6 +4553,211 @@ do_stat: + break; + #endif + ++ case TARGET_FREEBSD_NR_thr_new: ++ ret = do_thr_new(cpu_env, arg1, arg2); ++ break; ++ ++ case TARGET_FREEBSD_NR_thr_create: ++ { ++ ucontext_t ucxt; ++ long tid; ++ ++ ret = do_thr_create(cpu_env, &ucxt, &tid, arg3); ++ } ++ break; ++ ++ case TARGET_FREEBSD_NR_thr_set_name: ++ if (!(p = lock_user_string(arg2))) ++ goto efault; ++ ret = do_thr_set_name(arg1, p); ++ unlock_user(p, arg2, 0); ++ break; ++ ++ case TARGET_FREEBSD_NR_thr_self: ++ { ++ long tid; ++ ++ if ((ret = do_thr_self(&tid)) == 0) { ++ if (put_user((abi_long)tid, arg1, abi_long)) ++ goto efault; ++ } ++ } ++ break; ++ ++ case TARGET_FREEBSD_NR_thr_suspend: ++ { ++ struct timespec ts; ++ ++ if (target_to_host_timespec(&ts, arg1)) ++ goto efault; ++ ++ ret = do_thr_suspend(&ts); ++ } ++ break; ++ ++ case TARGET_FREEBSD_NR_thr_wake: ++ ret = do_thr_wake(arg1); ++ break; ++ ++ case TARGET_FREEBSD_NR_thr_kill: ++ ret = do_thr_kill(arg1, arg2); ++ break; ++ ++ case TARGET_FREEBSD_NR_thr_kill2: ++ ret = do_thr_kill2(arg1, arg2, arg3); ++ break; ++ ++ case TARGET_FREEBSD_NR_thr_exit: ++ ret = 0; /* suspress compile warning */ ++ do_thr_exit(cpu_env, arg1); ++ /* Shouldn't be reached. */ ++ break; ++ ++ case TARGET_FREEBSD_NR_rtprio_thread: ++ ret = 0; ++ break; ++ ++ case TARGET_FREEBSD_NR_getcontext: ++ { ++ target_ucontext_t *ucp; ++ sigset_t sigmask; ++ ++ if (0 == arg1) { ++ ret = -TARGET_EINVAL; ++ } else { ++ ret = get_errno(sigprocmask(0, NULL, &sigmask)); ++ if (!is_error(ret)) { ++ if (!(ucp = lock_user(VERIFY_WRITE, arg1, ++ sizeof(target_ucontext_t), 0))) ++ goto efault; ++ ret = get_mcontext(cpu_env, &ucp->uc_mcontext, ++ TARGET_MC_GET_CLEAR_RET); ++ host_to_target_sigset(&ucp->uc_sigmask, ++ &sigmask); ++ memset(ucp->__spare__, 0, ++ sizeof(ucp->__spare__)); ++ unlock_user(ucp, arg1, ++ sizeof(target_ucontext_t)); ++ } ++ } ++ } ++ break; ++ ++ case TARGET_FREEBSD_NR_setcontext: ++ { ++ target_ucontext_t *ucp; ++ sigset_t sigmask; ++ ++ if (0 == arg1) { ++ ret = -TARGET_EINVAL; ++ } else { ++ if (!(ucp = lock_user(VERIFY_READ, arg1, ++ sizeof(target_ucontext_t), 1))) ++ goto efault; ++ ret = set_mcontext(cpu_env, &ucp->uc_mcontext, 0); ++ target_to_host_sigset(&sigmask, &ucp->uc_sigmask); ++ unlock_user(ucp, arg1, sizeof(target_ucontext_t)); ++ if (0 == ret) ++ (void)sigprocmask(SIG_SETMASK, &sigmask, NULL); ++ } ++ } ++ break; ++ ++ case TARGET_FREEBSD_NR_swapcontext: ++ /* ++ * XXX Does anything besides old implementations of ++ * setjmp()/longjmp() uses these? ++ */ ++ ret = unimplemented(num); ++ break; ++ ++ case TARGET_FREEBSD_NR__umtx_lock: ++ { ++ long tid; ++ ++ thr_self(&tid); ++ ret = do_umtx_lock(arg1, tswap32(tid)); ++ } ++ break; ++ ++ case TARGET_FREEBSD_NR__umtx_unlock: ++ { ++ long tid; ++ ++ thr_self(&tid); ++ ret = do_umtx_unlock(arg1, tswap32(tid)); ++ } ++ break; ++ ++ case TARGET_FREEBSD_NR__umtx_op: ++ { ++ struct timespec ts; ++ void *object = NULL; ++ int operation; ++ void *addr = NULL; ++ void *addr2 = NULL; ++ ++ ++ /* int _umtx_op(void *obj, int op, u_long val, ++ * void *uaddr, void *uaddr2); */ ++ ++ abi_ulong obj = arg1; ++ int op = (int)arg2; ++ u_long val = arg3; ++ /* abi_ulong uaddr = arg4; */ ++ abi_ulong uaddr2 = arg5; ++ ++ switch(op) { ++ case TARGET_UMTX_OP_LOCK: ++ ret = do_umtx_lock(obj, tswap32((uint32_t)val)); ++ break; ++ ++ case TARGET_UMTX_OP_UNLOCK: ++ ret = do_umtx_unlock(obj, tswap32((uint32_t)val)); ++ break; ++ ++ case TARGET_UMTX_OP_WAIT: ++ if (uaddr2) { ++ if (target_to_host_timespec(&ts, uaddr2)) ++ goto efault; ++ addr2 = (void *)&ts; ++ } ++ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_WAIT, ++ tswap32(val), addr, addr2)); ++ break; ++ ++ case TARGET_UMTX_OP_WAKE: ++ operation = UMTX_OP_WAKE; ++ object = g2h(obj); ++ ret = get_errno(_umtx_op(g2h(obj), UMTX_OP_WAKE, ++ val, 0, 0)); ++ break; ++ ++ case TARGET_UMTX_OP_MUTEX_TRYLOCK: ++ case TARGET_UMTX_OP_MUTEX_LOCK: ++ case TARGET_UMTX_OP_MUTEX_UNLOCK: ++ case TARGET_UMTX_OP_SET_CEILING: ++ case TARGET_UMTX_OP_CV_WAIT: ++ case TARGET_UMTX_OP_CV_SIGNAL: ++ case TARGET_UMTX_OP_CV_BROADCAST: ++ case TARGET_UMTX_OP_WAIT_UINT: ++ case TARGET_UMTX_OP_RW_RDLOCK: ++ case TARGET_UMTX_OP_RW_WRLOCK: ++ case TARGET_UMTX_OP_RW_UNLOCK: ++ case TARGET_UMTX_OP_WAIT_UINT_PRIVATE: ++ case TARGET_UMTX_OP_WAKE_PRIVATE: ++ case TARGET_UMTX_OP_MUTEX_WAIT: ++ case TARGET_UMTX_OP_MUTEX_WAKE: ++ case TARGET_UMTX_OP_SEM_WAIT: ++ case TARGET_UMTX_OP_SEM_WAKE: ++ case TARGET_UMTX_OP_NWAKE_PRIVATE: ++ default: ++ ret = -TARGET_EINVAL; ++ break; ++ } ++ } ++ break; ++ + case TARGET_FREEBSD_NR_yield: + case TARGET_FREEBSD_NR_sched_setparam: + case TARGET_FREEBSD_NR_sched_getparam: +@@ -4146,36 +4768,18 @@ do_stat: + case TARGET_FREEBSD_NR_sched_get_priority_min: + case TARGET_FREEBSD_NR_sched_rr_get_interval: + +- + case TARGET_FREEBSD_NR_reboot: + case TARGET_FREEBSD_NR_shutdown: + + case TARGET_FREEBSD_NR_swapon: + case TARGET_FREEBSD_NR_swapoff: + +- case TARGET_FREEBSD_NR_thr_create: +- case TARGET_FREEBSD_NR_thr_exit: +- case TARGET_FREEBSD_NR_thr_self: +- case TARGET_FREEBSD_NR_thr_suspend: +- case TARGET_FREEBSD_NR_thr_wake: +- case TARGET_FREEBSD_NR_thr_new: +- case TARGET_FREEBSD_NR_thr_set_name: +- case TARGET_FREEBSD_NR_thr_kill2: +- +- case TARGET_FREEBSD_NR_getcontext: +- case TARGET_FREEBSD_NR_setcontext: +- case TARGET_FREEBSD_NR_swapcontext: +- +- case TARGET_FREEBSD_NR_rtprio_thread: + case TARGET_FREEBSD_NR_cpuset: + case TARGET_FREEBSD_NR_cpuset_getid: + case TARGET_FREEBSD_NR_cpuset_setid: + case TARGET_FREEBSD_NR_cpuset_getaffinity: + case TARGET_FREEBSD_NR_cpuset_setaffinity: + +- case TARGET_FREEBSD_NR__umtx_lock: +- case TARGET_FREEBSD_NR__umtx_unlock: +- + case TARGET_FREEBSD_NR_rctl_get_racct: + case TARGET_FREEBSD_NR_rctl_get_rules: + case TARGET_FREEBSD_NR_rctl_add_rule: +@@ -4185,16 +4789,6 @@ do_stat: + case TARGET_FREEBSD_NR_ntp_adjtime: + case TARGET_FREEBSD_NR_ntp_gettime: + +-#ifdef TARGET_FREEBSD_NR_getdomainname +- case TARGET_FREEBSD_NR_getdomainname: +-#endif +-#ifdef TARGET_FREEBSD_NR_setdomainname +- case TARGET_FREEBSD_NR_setdomainname: +-#endif +-#ifdef TARGET_FREEBSD_NR_uname +- case TARGET_FREEBSD_NR_uname: +-#endif +- + case TARGET_FREEBSD_NR_sctp_peeloff: + case TARGET_FREEBSD_NR_sctp_generic_sendmsg: + case TARGET_FREEBSD_NR_sctp_generic_recvmsg: +diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h +index ea1d25d..2879d83 100644 +--- a/bsd-user/syscall_defs.h ++++ b/bsd-user/syscall_defs.h +@@ -416,6 +416,11 @@ struct target_shmid_ds { + abi_ulong shm_ctime; /* time of last change by shmctl() */ + }; + ++#define TARGET_UCONTEXT_MAGIC 0xACEDBADE ++#define TARGET_MC_GET_CLEAR_RET 0x0001 ++#define TARGET_MC_ADD_MAGIC 0x0002 ++#define TARGET_MC_SET_ONSTACK 0x0004 ++ + /* this struct defines a stack used during syscall handling */ + typedef struct target_sigaltstack { + abi_long ss_sp; +@@ -477,95 +482,6 @@ typedef struct target_siginfo { + } _reason; + } target_siginfo_t; + +-#if defined(TARGET_MIPS) +- +-struct target_sigcontext { +- target_sigset_t sc_mask; /* signal mask to retstore */ +- int32_t sc_onstack; /* sigstack state to restore */ +- abi_long sc_pc; /* pc at time of signal */ +- abi_long sc_reg[32]; /* processor regs 0 to 31 */ +- abi_long mullo, mulhi; /* mullo and mulhi registers */ +- int32_t sc_fpused; /* fp has been used */ +- abi_long sc_fpregs[33]; /* fp regs 0 to 31 & csr */ +- abi_long sc_fpc_eir; /* fp exception instr reg */ +- /* int32_t reserved[8]; */ +-}; +- +-typedef struct target_mcontext { +- int32_t mc_onstack; /* sigstack state to restore */ +- abi_long mc_pc; /* pc at time of signal */ +- abi_long mc_regs[32]; /* process regs 0 to 31 */ +- abi_long sr; /* status register */ +- abi_long mullo, mulhi; +- int32_t mc_fpused; /* fp has been used */ +- abi_long mc_fpregs[33]; /* fp regs 0 to 32 & csr */ +- abi_long mc_fpc_eir; /* fp exception instr reg */ +- abi_ulong mc_tls; /* pointer to TLS area */ +-} target_mcontext_t; +- +-typedef struct target_ucontext { +- target_sigset_t uc_sigmask; +- target_mcontext_t uc_mcontext; +- target_ulong uc_link; +- target_stack_t uc_stack; +- int32_t uc_flags; +- int32_t __space__[8]; +-} target_ucontext_t; +- +-struct target_sigframe { +- abi_ulong sf_signum; +- abi_ulong sf_siginfo; /* code or pointer to sf_si */ +- abi_ulong sf_ucontext; /* points to sf_uc */ +- abi_ulong sf_addr; /* undocumented 4th arg */ +- target_ucontext_t sf_uc; /* = *sf_uncontext */ +- target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/ +- uint32_t __spare__[2]; +-}; +- +-#elif defined(TARGET_SPARC64) +- +-struct target_mcontext { +- uint64_t mc_global[8]; +- uint64_t mc_out[8]; +- uint64_t mc_local[8]; +- uint64_t mc_in[8]; +- uint32_t mc_fp[64]; +-} __aligned(64); +- +-typedef struct target_mcontext target_mcontext_t; +- +-typedef struct target_ucontext { +- target_sigset_t uc_sigmask; +- target_mcontext_t uc_mcontext; +- target_ulong uc_link; +- target_stack_t uc_stack; +- int32_t uc_flags; +- int32_t __space__[8]; +-} target_ucontext_t; +- +-struct target_sigframe { +- target_ucontext_t sf_uc; +- target_siginfo_t sf_si; +-}; +- +-#else +- +-typedef target_ulong target_mcontext_t; /* dummy */ +- +-#endif +- +-/* XXX where did this come from? +-typedef struct target_ucontext { +- target_ulong uc_flags; +- target_ulong uc_link; +- target_stack_t uc_stack; +- target_mcontext_t uc_mcontext; +- target_ulong uc_filer[80]; +- target_sigset_t uc_sigmask; +-} target_ucontext_t; +-*/ +- +- + #ifdef BSWAP_NEEDED + static inline void + tswap_sigset(target_sigset_t *d, const target_sigset_t *s) +@@ -603,3 +519,101 @@ void host_to_target_old_sigset(abi_ulong *old_sigset, const sigset_t *sigset); + void target_to_host_old_sigset(sigset_t *sigset, const abi_ulong *old_sigset); + int do_sigaction(int sig, const struct target_sigaction *act, + struct target_sigaction *oact); ++ ++ ++/* ++ * FreeBSD thread support. ++ */ ++ ++#define TARGET_THR_SUSPENDED 0x0001 ++#define TARGET_THR_SYSTEM_SCOPE 0x0002 ++ ++/* sysarch() ops */ ++#define TARGET_MIPS_SET_TLS 1 ++#define TARGET_MIPS_GET_TLS 2 ++ ++struct target_thr_param { ++ abi_ulong start_func; /* thread entry function. */ ++ abi_ulong arg; /* argument for entry function. */ ++ abi_ulong stack_base; /* stack base address. */ ++ abi_ulong stack_size; /* stack size. */ ++ abi_ulong tls_base; /* tls base address. */ ++ abi_ulong tls_size; /* tls size. */ ++ abi_ulong child_tid; /* address to store new TID. */ ++ abi_ulong parent_tid; /* parent access the new TID here. */ ++ abi_ulong rtp; /* Real-time scheduling priority. */ ++ abi_ulong spare[3]; /* spares. */ ++}; ++ ++struct target_rtprio { ++ uint16_t type; ++ uint16_t prio; ++}; ++ ++/* ++ * sys/_umtx.h ++ */ ++ ++struct target_umtx { ++ uint32_t u_owner; /* Owner of the mutex. */ ++}; ++ ++struct target_umutex { ++ uint32_t m_owner; /* Owner of the mutex */ ++ uint32_t m_flags; /* Flags of the mutex */ ++ uint32_t m_ceiling[2]; /* Priority protect ceiling */ ++ uint32_t m_spare[4]; ++}; ++ ++struct target_ucond { ++ uint32_t c_has_waiters; /* Has waiters in kernel */ ++ uint32_t c_flags; /* Flags of the condition variable */ ++ uint32_t c_clockid; /* Clock id */ ++ uint32_t c_spare[1]; ++}; ++ ++struct target_urwlock { ++ int32_t rw_state; ++ uint32_t rw_flags; ++ uint32_t rw_blocked_readers; ++ uint32_t rw_blocked_writers; ++ uint32_t rw_spare[4]; ++}; ++ ++struct target__usem { ++ uint32_t _has_waiters; ++ uint32_t _count; ++ uint32_t _flags; ++}; ++ ++/* ++ * sys/utmx.h ++ */ ++ ++/* op code for _umtx_op */ ++#define TARGET_UMTX_OP_LOCK 0 ++#define TARGET_UMTX_OP_UNLOCK 1 ++#define TARGET_UMTX_OP_WAIT 2 ++#define TARGET_UMTX_OP_WAKE 3 ++#define TARGET_UMTX_OP_MUTEX_TRYLOCK 4 ++#define TARGET_UMTX_OP_MUTEX_LOCK 5 ++#define TARGET_UMTX_OP_MUTEX_UNLOCK 6 ++#define TARGET_UMTX_OP_SET_CEILING 7 ++#define TARGET_UMTX_OP_CV_WAIT 8 ++#define TARGET_UMTX_OP_CV_SIGNAL 9 ++#define TARGET_UMTX_OP_CV_BROADCAST 10 ++#define TARGET_UMTX_OP_WAIT_UINT 11 ++#define TARGET_UMTX_OP_RW_RDLOCK 12 ++#define TARGET_UMTX_OP_RW_WRLOCK 13 ++#define TARGET_UMTX_OP_RW_UNLOCK 14 ++#define TARGET_UMTX_OP_WAIT_UINT_PRIVATE 15 ++#define TARGET_UMTX_OP_WAKE_PRIVATE 16 ++#define TARGET_UMTX_OP_MUTEX_WAIT 17 ++#define TARGET_UMTX_OP_MUTEX_WAKE 18 ++#define TARGET_UMTX_OP_SEM_WAIT 19 ++#define TARGET_UMTX_OP_SEM_WAKE 20 ++#define TARGET_UMTX_OP_NWAKE_PRIVATE 21 ++#define TARGET_UMTX_OP_MAX 22 ++ ++/* flags for UMTX_OP_CV_WAIT */ ++#define TARGET_CHECK_UNPARKING 0x01 +diff --git a/bsd-user/x86_64/target_signal.h b/bsd-user/x86_64/target_signal.h +index ea89f5a..a14e0b9 100644 +--- a/bsd-user/x86_64/target_signal.h ++++ b/bsd-user/x86_64/target_signal.h +@@ -15,4 +15,29 @@ static inline abi_ulong get_sp_from_cpustate(CPUX86State *state) + #define TARGET_MINSIGSTKSZ (512 * 4) + #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) + ++typedef target_ulong target_mcontext_t; /* dummy */ ++ ++typedef struct target_ucontext { ++ target_sigset_t uc_sigmask; ++ target_mcontext_t uc_mcontext; ++ abi_ulong uc_link; ++ target_stack_t uc_stack; ++ int32_t uc_flags; ++ int32_t __spare__[4]; ++} target_ucontext_t; ++ ++static inline int ++get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags) ++{ ++ fprintf(stderr, "x86_64 doesn't have support for get_mcontext()\n"); ++ return (-TARGET_ENOSYS); ++} ++ ++static inline int ++set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags) ++{ ++ fprintf(stderr, "x86_64 doesn't have support for set_mcontext()\n"); ++ return (-TARGET_ENOSYS); ++} ++ + #endif /* TARGET_SIGNAL_H */ +diff --git a/configure b/configure +index 34eca43..be75584 100755 +--- a/configure ++++ b/configure +@@ -1386,6 +1386,11 @@ fi + + if test "$nptl" != "no" ; then + cat > $TMPC <<EOF ++#ifdef __FreeBSD__ ++int main(void) { ++ return (0); ++} ++#else + #include <sched.h> + #include <linux/futex.h> + int main(void) { +@@ -1394,6 +1399,7 @@ int main(void) { + #endif + return 0; + } ++#endif + EOF + + if compile_object ; then +@@ -3751,5 +3757,6 @@ case "$target_arch2" in + TARGET_ARCH=mips64 + TARGET_BASE_ARCH=mips + echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak ++ target_nptl="yes" + target_long_alignment=8 + ;; |
