ports/emulators/qemu-devel/files/patch-zb-bsd-user-sson004a
Juergen Lock 45aa9370f0 - 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
2013-03-29 17:40:38 +00:00

1151 lines
36 KiB
Text

diff --git a/bsd-user/arm/syscall.h b/bsd-user/arm/syscall.h
index bd54b37..4d98841 100644
--- a/bsd-user/arm/syscall.h
+++ b/bsd-user/arm/syscall.h
@@ -22,4 +22,7 @@ struct target_pt_regs {
#define ARM_SYSCALL_BASE 0 /* XXX: FreeBSD only */
-#define TARGET_FREEBSD_ARM_SET_TP 2
+#define TARGET_FREEBSD_ARM_SYNC_ICACHE 0
+#define TARGET_FREEBSD_ARM_DRAIN_WRITEBUF 1
+#define TARGET_FREEBSD_ARM_SET_TP 2
+#define TARGET_FREEBSD_ARM_GET_TP 3
diff --git a/bsd-user/arm/target_signal.h b/bsd-user/arm/target_signal.h
index 4a9e518..05c9d1c 100644
--- a/bsd-user/arm/target_signal.h
+++ b/bsd-user/arm/target_signal.h
@@ -26,8 +26,6 @@
#define TARGET_REG_LR TARGET_REG_R14
#define TARGET_REG_PC TARGET_REG_R15
-#define TARGET_GET_MC_CLEAR_RET 1
-
#define TARGET_MINSIGSTKSZ (1024 * 4)
#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
#define TARGET__NGREG 17
@@ -109,7 +107,7 @@ get_sp_from_cpustate(CPUARMState *state)
* Compare to arm/arm/machdep.c sendsig()
* Assumes that the target stack frame memory is locked.
*/
-static inline int
+static inline abi_ulong
set_sigtramp_args(CPUARMState *regs, int sig, struct target_sigframe *frame,
abi_ulong frame_addr, struct target_sigaction *ka)
{
@@ -141,42 +139,89 @@ set_sigtramp_args(CPUARMState *regs, int sig, struct target_sigframe *frame,
}
/* Compare to arm/arm/machdep.c get_mcontext() */
-static inline int
+static inline abi_long
get_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int clear_ret)
{
- int i, err = 0;
+ int err = 0;
uint32_t *gr = mcp->__gregs;
- if (clear_ret & TARGET_GET_MC_CLEAR_RET)
+ if (clear_ret & TARGET_MC_GET_CLEAR_RET)
gr[TARGET_REG_R0] = 0;
else
gr[TARGET_REG_R0] = tswap32(regs->regs[0]);
- for(i = 1; i < 12; i++)
- gr[i] = tswap32(regs->regs[i]);
+
+ gr[TARGET_REG_R1 ] = tswap32(regs->regs[ 1]);
+ gr[TARGET_REG_R2 ] = tswap32(regs->regs[ 2]);
+ gr[TARGET_REG_R3 ] = tswap32(regs->regs[ 3]);
+ gr[TARGET_REG_R4 ] = tswap32(regs->regs[ 4]);
+ gr[TARGET_REG_R5 ] = tswap32(regs->regs[ 5]);
+ gr[TARGET_REG_R6 ] = tswap32(regs->regs[ 6]);
+ gr[TARGET_REG_R7 ] = tswap32(regs->regs[ 7]);
+ gr[TARGET_REG_R8 ] = tswap32(regs->regs[ 8]);
+ gr[TARGET_REG_R9 ] = tswap32(regs->regs[ 9]);
+ gr[TARGET_REG_R10] = tswap32(regs->regs[10]);
+ gr[TARGET_REG_R11] = tswap32(regs->regs[11]);
+ gr[TARGET_REG_R12] = tswap32(regs->regs[12]);
+
gr[TARGET_REG_SP] = tswap32(regs->regs[13]);
gr[TARGET_REG_LR] = tswap32(regs->regs[14]);
gr[TARGET_REG_PC] = tswap32(regs->regs[15]);
- gr[TARGET_REG_CPSR] = tswap32(regs->spsr);
+ gr[TARGET_REG_CPSR] = tswap32(cpsr_read(regs));
return (err);
}
/* Compare to arm/arm/machdep.c set_mcontext() */
-static inline int
-set_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int flags)
+static inline abi_long
+set_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int srflag)
{
- int i, err = 0;
+ int err = 0;
const uint32_t *gr = mcp->__gregs;
+ uint32_t cpsr;
+
+ regs->regs[ 0] = tswap32(gr[TARGET_REG_R0 ]);
+ regs->regs[ 1] = tswap32(gr[TARGET_REG_R1 ]);
+ regs->regs[ 2] = tswap32(gr[TARGET_REG_R2 ]);
+ regs->regs[ 3] = tswap32(gr[TARGET_REG_R3 ]);
+ regs->regs[ 4] = tswap32(gr[TARGET_REG_R4 ]);
+ regs->regs[ 5] = tswap32(gr[TARGET_REG_R5 ]);
+ regs->regs[ 6] = tswap32(gr[TARGET_REG_R6 ]);
+ regs->regs[ 7] = tswap32(gr[TARGET_REG_R7 ]);
+ regs->regs[ 8] = tswap32(gr[TARGET_REG_R8 ]);
+ regs->regs[ 9] = tswap32(gr[TARGET_REG_R9 ]);
+ regs->regs[10] = tswap32(gr[TARGET_REG_R10]);
+ regs->regs[11] = tswap32(gr[TARGET_REG_R11]);
+ regs->regs[12] = tswap32(gr[TARGET_REG_R12]);
- for(i = 0; i < 12; i++)
- regs->regs[i] = tswap32(gr[i]);
regs->regs[13] = tswap32(gr[TARGET_REG_SP]);
regs->regs[14] = tswap32(gr[TARGET_REG_LR]);
regs->regs[15] = tswap32(gr[TARGET_REG_PC]);
- regs->spsr = tswap32(gr[TARGET_REG_CPSR]);
+ cpsr = tswap32(gr[TARGET_REG_CPSR]);
+ cpsr_write(regs, cpsr, CPSR_USER | CPSR_EXEC);
return (err);
}
+/* Compare to arm/arm/machdep.c sys_sigreturn() */
+static inline abi_long
+get_ucontext_sigreturn(CPUARMState *regs, abi_ulong sf_addr,
+ target_ucontext_t **ucontext, void **locked_addr)
+{
+ struct target_sigframe *sf;
+ uint32_t cpsr = cpsr_read(regs);
+
+ if ((cpsr & CPSR_M) != ARM_CPU_MODE_USR ||
+ (cpsr & (CPSR_I | CPSR_F)) != 0)
+ return (-TARGET_EINVAL);
+
+ if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 0))
+ return (-TARGET_EFAULT);
+
+ *locked_addr = sf;
+ *ucontext = (target_ucontext_t *)g2h(tswapal(sf_addr +
+ offsetof(struct target_sigframe, sf_uc)));
+ return (0);
+}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 76681e1..7a7c3eb 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -13,6 +13,7 @@
#include "qemu.h"
#include "disas/disas.h"
+#include "target_signal.h"
#ifdef _ARCH_PPC64
#undef ARCH_DLINFO
diff --git a/bsd-user/errno_defs.h b/bsd-user/errno_defs.h
index 1efa502..7f2e0ca 100644
--- a/bsd-user/errno_defs.h
+++ b/bsd-user/errno_defs.h
@@ -147,3 +147,7 @@
#define TARGET_EIDRM 89 /* Identifier removed */
#define TARGET_ENOMSG 90 /* No message of desired type */
#define TARGET_ELAST 90 /* Must be equal largest errno */
+
+/* pseudo-errors just used in the kernel/emulator: */
+#define TARGET_ERESTART 255 /* restart syscall */
+#define TARGET_EJUSTRETURN 254 /* Don't modify regs, just ret */
diff --git a/bsd-user/freebsd/strace.list b/bsd-user/freebsd/strace.list
index 8270c37..1f8ee10 100644
--- a/bsd-user/freebsd/strace.list
+++ b/bsd-user/freebsd/strace.list
@@ -33,6 +33,7 @@
{ TARGET_FREEBSD_NR_connect, "connect", "%s(%d,%#x,%d)", NULL, NULL },
{ TARGET_FREEBSD_NR_dup, "dup", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_dup2, "dup2", NULL, NULL, NULL },
+{ TARGET_FREEBSD_NR_eaccess, "eaccess", "%s(%s,%#x)", NULL, NULL },
{ TARGET_FREEBSD_NR_execve, "execve", NULL, print_execve, NULL },
{ TARGET_FREEBSD_NR_exit, "exit", "%s(%d)\n", NULL, NULL },
{ TARGET_FREEBSD_NR_extattrctl, "extattrctl", "%s(\"%s\", %d, \"%s\", %d, \"%s\"", NULL, NULL },
@@ -51,7 +52,7 @@
{ TARGET_FREEBSD_NR_fchdir, "fchdir", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_fchflags, "fchflags", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_fchmod, "fchmod", "%s(%d,%#o)", NULL, NULL },
-{ TARGET_FREEBSD_NR_fchown, "fchown", "%s(\"%s\",%d,%d)", NULL, NULL },
+{ TARGET_FREEBSD_NR_fchown, "fchown", "%s(%d,%d,%d)", NULL, NULL },
{ TARGET_FREEBSD_NR_fcntl, "fcntl", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_fexecve, "fexecve", NULL, print_execve, NULL },
{ TARGET_FREEBSD_NR_fhopen, "fhopen", NULL, NULL, NULL },
@@ -185,7 +186,7 @@
{ TARGET_FREEBSD_NR_sigprocmask, "sigprocmask", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_sigreturn, "sigreturn", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_sigsuspend, "sigsuspend", NULL, NULL, NULL },
-{ TARGET_FREEBSD_NR_socket, "socket", NULL, NULL, NULL },
+{ TARGET_FREEBSD_NR_socket, "socket", "%s(%d,%d,%d)", NULL, NULL },
{ TARGET_FREEBSD_NR_socketpair, "socketpair", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_sstk, "sstk", NULL, NULL, NULL },
{ TARGET_FREEBSD_NR_stat, "stat", "%s(\"%s\",%p)", NULL, NULL },
diff --git a/bsd-user/i386/target_signal.h b/bsd-user/i386/target_signal.h
index 28481ce..51a2a7b 100644
--- a/bsd-user/i386/target_signal.h
+++ b/bsd-user/i386/target_signal.h
@@ -3,11 +3,6 @@
#include "cpu.h"
-static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
-{
- return state->regs[R_ESP];
-}
-
#define TARGET_MINSIGSTKSZ (512 * 4)
#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768)
@@ -22,18 +17,32 @@ typedef struct target_ucontext {
int32_t __spare__[4];
} target_ucontext_t;
-static inline int
+static inline abi_ulong
+get_sp_from_cpustate(CPUX86State *state)
+{
+ return state->regs[R_ESP];
+}
+
+static inline abi_long
get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
{
fprintf(stderr, "i386 doesn't have support for get_mcontext()\n");
return (-TARGET_ENOSYS);
}
-static inline int
+static inline abi_long
set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
{
fprintf(stderr, "i386 doesn't have support for set_mcontext()\n");
return (-TARGET_ENOSYS);
}
+static inline abi_long
+get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
+ target_ucontext_t **ucontext, void **locked_addr)
+{
+ fprintf(stderr, "i386 doesn't have support for do_sigreturn()\n");
+ return (-TARGET_ENOSYS);
+}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/bsd-user/main.c b/bsd-user/main.c
index b6aaa7e..b248a91 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -35,6 +35,7 @@
#include "tcg.h"
#include "qemu/timer.h"
#include "qemu/envlist.h"
+#include "target_signal.h"
#if defined(CONFIG_USE_NPTL) && defined(__FreeBSD__)
#include <sys/thr.h>
@@ -813,15 +814,25 @@ void cpu_loop(CPUARMState *env)
arg6,
arg7,
arg8);
- if ((unsigned int)ret >= (unsigned int)(-515)) {
- ret = -ret;
- cpsr_write(env, CPSR_C, CPSR_C);
- env->regs[0] = ret;
- } else {
- cpsr_write(env, 0, CPSR_C);
- env->regs[0] = ret; // XXX need to handle lseek()?
- // env->regs[1] = 0;
- }
+ /* Compare to arm/arm/vm_machdep.c cpu_set_syscall_retval() */
+ /* XXX armeb may need some extra magic here */
+ if (-TARGET_EJUSTRETURN == ret) {
+ /*
+ * Returning from a successful sigreturn syscall.
+ * Avoid clobbering register state.
+ */
+ break;
+ }
+ /* XXX Need to handle ERESTART. Backup the PC by 1 instruction*/
+ if ((unsigned int)ret >= (unsigned int)(-515)) {
+ ret = -ret;
+ cpsr_write(env, CPSR_C, CPSR_C);
+ env->regs[0] = ret;
+ } else {
+ cpsr_write(env, 0, CPSR_C);
+ env->regs[0] = ret; // XXX need to handle lseek()?
+ // env->regs[1] = 0;
+ }
} else {
// XXX is this correct?
env->regs[0] = do_openbsd_syscall(env,
@@ -1068,13 +1079,20 @@ void cpu_loop(CPUMIPSState *env)
}
}
/* done_syscall: */
- if (-TARGET_QEMU_ESIGRETURN == ret) {
+ /*
+ * Compare to mips/mips/vm_machdep.c
+ * cpu_set_syscall_retval()
+ *
+ * XXX need to handle lseek here.
+ */
+ if (-TARGET_EJUSTRETURN == ret) {
/*
* Returning from a successful sigreturn
* syscall. Avoid clobbering register state.
*/
break;
}
+ /* XXX need to handle ERESTART */
if ((unsigned int)ret >= (unsigned int)(-1133)) {
env->active_tc.gpr[7] = 1;
ret = -ret;
diff --git a/bsd-user/mips/target_signal.h b/bsd-user/mips/target_signal.h
index 484cfd8..0f57f0f 100644
--- a/bsd-user/mips/target_signal.h
+++ b/bsd-user/mips/target_signal.h
@@ -61,7 +61,7 @@ get_sp_from_cpustate(CPUMIPSState *state)
* Compare to mips/mips/pm_machdep.c sendsig()
* Assumes that "frame" memory is locked.
*/
-static inline int
+static inline abi_long
set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
abi_ulong frame_addr, struct target_sigaction *ka)
{
@@ -98,7 +98,7 @@ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
* Compare to mips/mips/pm_machdep.c get_mcontext()
* Assumes that the memory is locked if mcp points to user memory.
*/
-static inline int
+static inline abi_long
get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
{
int i, err = 0;
@@ -152,8 +152,8 @@ get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
}
/* Compare to mips/mips/pm_machdep.c set_mcontext() */
-static inline int
-set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
+static inline abi_long
+set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int srflag)
{
int i, err = 0;
@@ -184,9 +184,27 @@ set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
regs->active_tc.HI[0] = tswapal(mcp->mulhi);
regs->tls_value = tswapal(mcp->mc_tls);
+ if (srflag) {
+ /* doing sigreturn() */
+ regs->active_tc.PC = regs->CP0_EPC;
+ regs->CP0_EPC = 0; /* XXX for nested signals ? */
+ }
+
/* Don't do any of the status and cause registers. */
return (err);
}
+/* mips/mips/pm_machdep.c sys_sigreturn() */
+static inline abi_long
+get_ucontext_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr,
+ target_ucontext_t **ucontext, void **locked_addr)
+{
+ if (!lock_user_struct(VERIFY_READ, *ucontext, uc_addr, 0))
+ return (-TARGET_EFAULT);
+
+ *locked_addr = *ucontext;
+ return (0);
+}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h
index f657909..3fee772 100644
--- a/bsd-user/mips64/target_signal.h
+++ b/bsd-user/mips64/target_signal.h
@@ -58,7 +58,7 @@ get_sp_from_cpustate(CPUMIPSState *state)
#define TARGET_SZSIGCODE (4 * 4)
/* Compare to mips/mips/locore.S sigcode() */
-static inline int
+static inline abi_long
install_sigtramp(abi_ulong offset, unsigned sigf_uc, unsigned sys_sigreturn)
{
int i;
@@ -79,7 +79,7 @@ install_sigtramp(abi_ulong offset, unsigned sigf_uc, unsigned sys_sigreturn)
* Compare to mips/mips/pm_machdep.c sendsig()
* Assumes that target stack frame memory is locked.
*/
-static inline int
+static inline abi_long
set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
abi_ulong frame_addr, struct target_sigaction *ka)
{
@@ -117,7 +117,7 @@ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame,
* Compare to mips/mips/pm_machdep.c get_mcontext()
* Assumes that the memory is locked if mcp points to user memory.
*/
-static inline int
+static inline abi_long
get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
{
int i, err = 0;
@@ -171,8 +171,8 @@ get_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
}
/* Compare to mips/mips/pm_machdep.c set_mcontext() */
-static inline int
-set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
+static inline abi_long
+set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int srflag)
{
int i, err = 0;
@@ -203,10 +203,28 @@ set_mcontext(CPUMIPSState *regs, target_mcontext_t *mcp, int flags)
regs->active_tc.HI[0] = tswapal(mcp->mulhi);
regs->tls_value = tswapal(mcp->mc_tls);
+ if (srflag) {
+ /* doing sigreturn() */
+ regs->active_tc.PC = regs->CP0_EPC;
+ regs->CP0_EPC = 0; /* XXX for nested signals ? */
+ }
+
/* Don't do any of the status and cause registers. */
return (err);
}
+/* mips/mips/pm_machdep.c sys_sigreturn() */
+static inline abi_long
+get_ucontext_sigreturn(CPUMIPSState *regs, abi_ulong uc_addr,
+ target_ucontext_t **ucontext, void **locked_addr)
+{
+ if (!lock_user_struct(VERIFY_READ, *ucontext, uc_addr, 0))
+ return (-TARGET_EFAULT);
+
+ *locked_addr = *ucontext;
+ return (0);
+}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index d51f50c..fbcdd6c 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -27,7 +27,6 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src,
#include "syscall_defs.h"
#include "syscall.h"
#include "target_vmparam.h"
-#include "target_signal.h"
#include "exec/gdbstub.h"
#if defined(CONFIG_USE_NPTL)
diff --git a/bsd-user/signal.c b/bsd-user/signal.c
index b04e874..e7e9e41 100644
--- a/bsd-user/signal.c
+++ b/bsd-user/signal.c
@@ -101,6 +101,9 @@ static struct target_sigaction sigact_table[TARGET_NSIG];
static void host_signal_handler(int host_signum, siginfo_t *info, void *puc);
+static void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s);
+void QEMU_NORETURN force_sig(int target_sig);
+
static inline int
on_sig_stack(unsigned long sp)
{
@@ -315,7 +318,7 @@ free_sigqueue(CPUArchState *env, struct qemu_sigqueue *q)
}
/* Abort execution with signal. */
-static void QEMU_NORETURN
+void QEMU_NORETURN
force_sig(int target_sig)
{
TaskState *ts = (TaskState *)thread_env->opaque;
@@ -728,194 +731,20 @@ give_sigsegv:
force_sig(TARGET_SIGSEGV);
}
-long
-do_sigreturn(CPUArchState *regs, abi_ulong uc_addr)
-{
- target_ucontext_t *ucontext;
- sigset_t blocked;
- target_sigset_t target_set;
- int i;
-
-#if defined(DEBUG_SIGNAL)
- fprintf(stderr, "do_sigreturn\n");
-#endif
- if (!lock_user_struct(VERIFY_READ, ucontext, uc_addr, 1))
- goto badframe;
-
- for(i = 0; i < TARGET_NSIG_WORDS; i++) {
- if (__get_user(target_set.__bits[i], &ucontext->uc_sigmask.__bits[i]))
- goto badframe;
- }
-
- if (set_mcontext(regs, &ucontext->uc_mcontext, 0))
- goto badframe;
-
- target_to_host_sigset_internal(&blocked, &target_set);
- sigprocmask(SIG_SETMASK, &blocked, NULL);
-
-#if defined(TARGET_MIPS)
- CPUMIPSState *mips_regs = (CPUMIPSState *)regs;
- mips_regs->active_tc.PC = mips_regs->CP0_EPC;
- mips_regs->CP0_EPC = 0; /* XXX for nested signals ? */
-#endif
- return (-TARGET_QEMU_ESIGRETURN);
-
-badframe:
- force_sig(TARGET_SIGSEGV);
- return (0);
-}
-
-
-
-/* #elif defined(TARGET_SPARC64) */
-#if 0
-
-#define mc_flags mc_global[0]
-#define mc_sp mc_out[6]
-#define mc_fprs mc_local[0]
-#define mc_fsr mc_local[1]
-#define mc_qsr mc_local[2]
-#define mc_tnpc mc_in[0]
-#define mc_tpc mc_in[1]
-#define mc_tstate mc_in[2]
-#define mc_y mc_in[4]
-#define mc_wstate mc_in[5]
-
-#define ureg_i0 regwptr[0 ]
-#define ureg_i1 regwptr[1 ]
-#define ureg_i2 regwptr[2 ]
-#define ureg_i3 regwptr[3 ]
-#define ureg_i4 regwptr[4 ]
-#define ureg_i5 regwptr[5 ]
-#define ureg_i6 regwptr[6 ]
-#define ureg_i7 regwptr[7 ]
-#define ureg_l0 regwptr[8 ]
-#define ureg_l1 regwptr[9 ]
-#define ureg_l2 regwptr[10]
-#define ureg_l3 regwptr[11]
-#define ureg_l4 regwptr[12]
-#define ureg_l5 regwptr[13]
-#define ureg_l6 regwptr[14]
-#define ureg_l7 regwptr[15]
-#define ureg_o0 regwptr[16]
-#define ureg_o1 regwptr[17]
-#define ureg_o2 regwptr[18]
-#define ureg_o3 regwptr[19]
-#define ureg_o4 regwptr[20]
-#define ureg_o5 regwptr[21]
-#define ureg_o6 regwptr[22]
-#define ureg_o7 regwptr[23]
-#define ureg_fp ureg_i6
-#define ureg_sp ureg_o6
-#define ureg_tnpc ureg_i0
-#define ureg_tpc ureg_i1
-
-#define TARGET_FPRS_FEF (1 << 2)
-#define TARGET_MC_VERSION 1L
-
-/* compare to sparc64/sparc64/machdep.c set_mcontext() */
-static inline int
-restore_sigmcontext(CPUSPARCState *regs, target_mcontext_t *mc)
-{
- int err = 0;
-
- err |= __get_user(regs->gregs[1], &mc->mc_global[1]);
- err |= __get_user(regs->gregs[2], &mc->mc_global[2]);
- err |= __get_user(regs->gregs[3], &mc->mc_global[3]);
- err |= __get_user(regs->gregs[4], &mc->mc_global[4]);
- err |= __get_user(regs->gregs[5], &mc->mc_global[5]);
- err |= __get_user(regs->gregs[6], &mc->mc_global[6]);
-
- err |= __get_user(regs->ureg_o0, &mc->mc_out[0]);
- err |= __get_user(regs->ureg_o1, &mc->mc_out[1]);
- err |= __get_user(regs->ureg_o2, &mc->mc_out[2]);
- err |= __get_user(regs->ureg_o3, &mc->mc_out[3]);
- err |= __get_user(regs->ureg_o4, &mc->mc_out[4]);
- err |= __get_user(regs->ureg_o5, &mc->mc_out[5]);
- err |= __get_user(regs->ureg_o6, &mc->mc_out[6]);
- err |= __get_user(regs->ureg_o7, &mc->mc_out[0]);
-
- err |= __get_user(regs->ureg_l0, &mc->mc_fprs); /* mc_local[0] */
- err |= __get_user(regs->ureg_l1, &mc->mc_fsr); /* mc_local[1] */
- err |= __get_user(regs->ureg_l2, &mc->mc_qsr); /* mc_local[2] */
-
- err |= __get_user(regs->ureg_i0, &mc->mc_tnpc); /* mc_in[0] */
- err |= __get_user(regs->ureg_i1, &mc->mc_tpc); /* mc_in[1] */
- err |= __get_user(regs->ureg_i2, &mc->mc_tstate);/* mc_in[2] */
-
- err |= __get_user(regs->ureg_i4, &mc->mc_y); /* mc_in[4] */
-
- /* XXX
- if ((regs->ureg_l0 & TARGET_FPRS_FEF) != 0) {
- regs->ureg_l0 = 0;
- for(i = 0; i < 64; i++)
- err |= __get_user(regs->fpr[i], &mc->mc_fp[i]);
- }
- */
-
- return (err);
-}
+#else
-/* compare to sparc64/sparc64/machdep.c get_mcontext() */
-static inline int
-setup_sigmcontext(CPUSPARCState *regs, target_mcontext_t *mc)
+static void
+setup_frame(int sig, int code, struct target_sigaction *ka, target_sigset_t *set,
+ target_siginfo_t *tinfo, CPUArchState *env)
{
- int err = 0;
- abi_ulong ver = TARGET_MC_VERSION;
-
- err |= __put_user(ver, &mc->mc_flags); /* aka. mc_global[0] */
- err |= __put_user(regs->gregs[1], &mc->mc_global[1]);
- err |= __put_user(regs->gregs[2], &mc->mc_global[2]);
- err |= __put_user(regs->gregs[3], &mc->mc_global[3]);
- err |= __put_user(regs->gregs[4], &mc->mc_global[4]);
- err |= __put_user(regs->gregs[5], &mc->mc_global[5]);
- err |= __put_user(regs->gregs[6], &mc->mc_global[6]);
- /* skip %g7 since it is used as the userland TLS register */
-
- err |= __put_user(regs->ureg_o0, &mc->mc_out[0]);
- err |= __put_user(regs->ureg_o1, &mc->mc_out[1]);
- err |= __put_user(regs->ureg_o2, &mc->mc_out[2]);
- err |= __put_user(regs->ureg_o3, &mc->mc_out[3]);
- err |= __put_user(regs->ureg_o4, &mc->mc_out[4]);
- err |= __put_user(regs->ureg_o5, &mc->mc_out[5]);
- err |= __put_user(regs->ureg_o6, &mc->mc_out[6]);
- err |= __put_user(regs->ureg_o7, &mc->mc_out[7]);
-
- err |= __put_user(regs->ureg_l0, &mc->mc_fprs); /* mc_local[0] */
- err |= __put_user(regs->ureg_l1, &mc->mc_fsr); /* mc_local[1] */
- err |= __put_user(regs->ureg_l2, &mc->mc_qsr); /* mc_local[2] */
- err |= __put_user(regs->ureg_i0, &mc->mc_tnpc); /* mc_in[0] */
- err |= __put_user(regs->ureg_i1, &mc->mc_tpc); /* mc_in[1] */
- err |= __put_user(regs->ureg_i2, &mc->mc_tstate);/* mc_in[2] */
-
- err |= __put_user(regs->ureg_i4, &mc->mc_y); /* mc_in[4] */
-
- /* XXX
- if ((regs->ureg_l0 & TARGET_FPRS_FEF) != 0) {
- for(i = 0; i < 64; i++)
- err |= __put_user(regs->fpr[i], &mc->mc_fp[i]);
- }
- */
-
- return (err);
+ fprintf(stderr, "setup_frame: not implemented\n");
}
-static inline abi_ulong
-get_sigframe(struct target_sigaction *ka, CPUSPARCState *regs, size_t frame_size)
-{
- abi_ulong sp;
+#endif /* ! TARGET_ARM && TARGET_MIPS */
- /* Use default user stack */
- sp = regs->ureg_sp;
-
- if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) {
- sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
- }
-
- return (sp - frame_size);
-}
+#if 0
/* compare to sparc64/sparc64/machdep.c sendsig() */
static void setup_frame(int sig, int code, struct target_sigaction *ka,
target_sigset_t *set, target_siginfo_t *tinfo, CPUSPARCState *regs)
@@ -974,64 +803,60 @@ give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
force_sig(TARGET_SIGSEGV);
}
+#endif
-
-long do_sigreturn(CPUSPARCState *regs, abi_ulong uc_addr)
+static int
+reset_signal_mask(target_ucontext_t *ucontext)
{
- target_ucontext_t *ucontext;
+ int i;
sigset_t blocked;
target_sigset_t target_set;
- int i;
-#if defined(DEBUG_SIGNAL)
- fprintf(stderr, "do_sigreturn\n");
-#endif
- if (!lock_user_struct(VERIFY_READ, ucontext, uc_addr, 1))
- goto badframe;
+ for(i = 0; i < TARGET_NSIG_WORDS; i++)
+ if (__get_user(target_set.__bits[i],
+ &ucontext->uc_sigmask.__bits[i])) {
+ return (-TARGET_EFAULT);
+ }
+ target_to_host_sigset_internal(&blocked, &target_set);
+ sigprocmask(SIG_SETMASK, &blocked, NULL);
- for(i = 0; i < TARGET_NSIG_WORDS; i++) {
- if (__get_user(target_set.__bits[i], &ucontext->uc_sigmask.__bits[i]))
+ return (0);
+}
+
+long
+do_sigreturn(CPUArchState *regs, abi_ulong addr)
+{
+ int ret;
+ target_ucontext_t *ucontext;
+ void *locked_addr = NULL;
+
+ /* Lock the memory and get the ucontext ptr from the stack frame */
+ ret = get_ucontext_sigreturn(regs, addr, &ucontext, &locked_addr);
+ if (ret) {
+ if (-TARGET_EFAULT == ret)
goto badframe;
+ else
+ return (ret);
}
- if (restore_sigmcontext(regs, &ucontext->uc_mcontext))
+ /* Set the register state back to before the signal. */
+ if (set_mcontext(regs, &ucontext->uc_mcontext, 1))
goto badframe;
- target_to_host_sigset_internal(&blocked, &target_set);
- sigprocmask(SIG_SETMASK, &blocked, NULL);
+ /* And reset the signal mask. */
+ if (reset_signal_mask(ucontext))
+ goto badframe;
- return (-TARGET_QEMU_ESIGRETURN);
+ unlock_user_struct(locked_addr, addr, 0);
+ return (-TARGET_EJUSTRETURN);
badframe:
+ if (locked_addr != NULL)
+ unlock_user_struct(locked_addr, addr, 0);
force_sig(TARGET_SIGSEGV);
- return (0);
-}
-#endif
-
-#else
-
-static void
-setup_frame(int sig, int code, struct target_sigaction *ka, target_sigset_t *set,
- target_siginfo_t *tinfo, CPUArchState *env)
-{
- fprintf(stderr, "setup_frame: not implemented\n");
-}
-
-long
-do_sigreturn(CPUArchState *env, abi_ulong uc_addr)
-{
- fprintf(stderr,"do_sigreturn: not implemented\n");
- return (-TARGET_ENOSYS);
+ return (-TARGET_EFAULT);
}
-long
-do_rt_sigreturn(CPUArchState *env)
-{
- fprintf(stderr, "do_rt_sigreturn: not implemented\n");
- return (-TARGET_ENOSYS);
-}
-#endif
-
void
signal_init(void)
{
diff --git a/bsd-user/sparc/target_signal.h b/bsd-user/sparc/target_signal.h
index e2fe79c..65d315a 100644
--- a/bsd-user/sparc/target_signal.h
+++ b/bsd-user/sparc/target_signal.h
@@ -43,4 +43,12 @@ set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
return (-TARGET_ENOSYS);
}
+static inline abi_long
+get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
+ target_ucontext_t **ucontext, void **locked_addr)
+{
+ fprintf(stderr, "SPARC doesn't have support for do_sigreturn()\n");
+ return (-TARGET_ENOSYS);
+}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/bsd-user/sparc64/target_signal.h b/bsd-user/sparc64/target_signal.h
index 1bc7c96..fa8edb8 100644
--- a/bsd-user/sparc64/target_signal.h
+++ b/bsd-user/sparc64/target_signal.h
@@ -245,4 +245,12 @@ set_mcontext(CPUSPARCState *regs, target_mcontext_t *mcp, int flags)
return (0);
}
+static inline abi_long
+get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
+ target_ucontext_t **ucontext, void **locked_addr)
+{
+ fprintf(stderr, "SPARC64 doesn't have support for do_sigreturn()\n");
+ return (-TARGET_ENOSYS);
+}
+
#endif /* TARGET_SIGNAL_H */
diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c
index 636083a..2d97a23 100644
--- a/bsd-user/syscall.c
+++ b/bsd-user/syscall.c
@@ -90,12 +90,12 @@
#include "qemu.h"
#include "qemu-common.h"
+#include "target_signal.h"
#ifdef __FreeBSD__
#include "freebsd/ttycom.h"
#include "freebsd/filio.h"
#endif
-
//#define DEBUG
static abi_ulong target_brk;
@@ -346,32 +346,47 @@ static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
#endif
#ifdef TARGET_ARM
-static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+static abi_long do_freebsd_sysarch(CPUARMState *env, int op, abi_ulong parms)
{
+ int ret = 0;
switch (op) {
+ case TARGET_FREEBSD_ARM_SYNC_ICACHE:
+ case TARGET_FREEBSD_ARM_DRAIN_WRITEBUF:
+ break;
+
case TARGET_FREEBSD_ARM_SET_TP:
cpu_set_tls(env, parms);
- return 0;
+ break;
+
+ case TARGET_FREEBSD_ARM_GET_TP:
+ /* XXX Need a cpu_get_tls() */
+ if (put_user(env->cp15.c13_tls2, parms, abi_ulong))
+ ret = -TARGET_EFAULT;
+ break;
+
+ default:
+ ret = -TARGET_EINVAL;
+ break;
}
- return -TARGET_EINVAL;
+ return (ret);
}
#endif
#ifdef TARGET_MIPS
-static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
+static abi_long do_freebsd_sysarch(CPUMIPSState *env, int op, abi_ulong parms)
{
int ret = 0;
- CPUMIPSState *mips_env = (CPUMIPSState *)env;
switch(op) {
case TARGET_MIPS_SET_TLS:
- mips_env->tls_value = parms;
+ cpu_set_tls(env, parms);
break;
case TARGET_MIPS_GET_TLS:
- if (put_user(mips_env->tls_value, parms, abi_ulong))
+ /* XXX Need a cpu_get_tls() */
+ if (put_user(env->tls_value, parms, abi_ulong))
ret = -TARGET_EFAULT;
break;
default:
@@ -671,7 +686,7 @@ target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
if (!target_saddr)
return -TARGET_EFAULT;
- sa_family = tswap16(target_saddr->sa_family);
+ sa_family = target_saddr->sa_family;
/*
* Oops. The caller might send a incomplete sun_path; sun_path
@@ -680,7 +695,7 @@ target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
* "strlen(x->sun_path)" while it should be "strlen(...) + 1". We will
* fix that here if needed.
*/
- if (sa_family == AF_UNIX) {
+ if (target_saddr->sa_family == AF_UNIX) {
if (len < unix_maxlen && len > 0) {
char *cp = (char*)target_saddr;
@@ -692,7 +707,8 @@ target_to_host_sockaddr(struct sockaddr *addr, abi_ulong target_addr,
}
memcpy(addr, target_saddr, len);
- addr->sa_family = sa_family;
+ addr->sa_family = sa_family; /* type uint8_t */
+ addr->sa_len = target_saddr->sa_len; /* type uint8_t */
unlock_user(target_saddr, target_addr, 0);
return (0);
@@ -708,7 +724,8 @@ host_to_target_sockaddr(abi_ulong target_addr, struct sockaddr *addr,
if (!target_saddr)
return (-TARGET_EFAULT);
memcpy(target_saddr, addr, len);
- target_saddr->sa_family = tswap16(addr->sa_family);
+ target_saddr->sa_family = addr->sa_family; /* type uint8_t */
+ target_saddr->sa_len = addr->sa_len; /* type uint8_t */
unlock_user(target_saddr, target_addr, len);
return (0);
@@ -1427,7 +1444,7 @@ static abi_long
do_sendto(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
socklen_t addrlen)
{
- void *addr;
+ struct sockaddr *saddr;
void *host_msg;
abi_long ret;
@@ -1437,13 +1454,13 @@ do_sendto(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
if (!host_msg)
return (-TARGET_EFAULT);
if (target_addr) {
- addr = alloca(addrlen);
- ret = target_to_host_sockaddr(addr, target_addr, addrlen);
+ saddr = alloca(addrlen);
+ ret = target_to_host_sockaddr(saddr, target_addr, addrlen);
if (ret) {
unlock_user(host_msg, msg, 0);
return (ret);
}
- ret = get_errno(sendto(fd, host_msg, len, flags, addr,
+ ret = get_errno(sendto(fd, host_msg, len, flags, saddr,
addrlen));
} else {
ret = get_errno(send(fd, host_msg, len, flags));
@@ -1458,7 +1475,7 @@ do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
abi_ulong target_addrlen)
{
socklen_t addrlen;
- void *addr;
+ struct sockaddr *saddr;
void *host_msg;
abi_long ret;
@@ -1474,16 +1491,16 @@ do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, abi_ulong target_addr,
ret = (-TARGET_EINVAL);
goto fail;
}
- addr = alloca(addrlen);
- ret = get_errno(recvfrom(fd, host_msg, len, flags, addr,
+ saddr = alloca(addrlen);
+ ret = get_errno(recvfrom(fd, host_msg, len, flags, saddr,
&addrlen));
} else {
- addr = NULL; /* To keep compiler quiet. */
+ saddr = NULL; /* To keep compiler quiet. */
ret = get_errno(qemu_recv(fd, host_msg, len, flags));
}
if (!is_error(ret)) {
if (target_addr) {
- host_to_target_sockaddr(target_addr, addr, addrlen);
+ host_to_target_sockaddr(target_addr, saddr, addrlen);
if (put_user_u32(addrlen, target_addrlen)) {
ret = -TARGET_EFAULT;
goto fail;
@@ -5670,8 +5687,8 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
return (-TARGET_EFAULT);
fl.l_type = tswap16(target_fl->l_type);
fl.l_whence = tswap16(target_fl->l_whence);
- fl.l_start = tswapal(target_fl->l_start);
- fl.l_len = tswapal(target_fl->l_len);
+ fl.l_start = tswap64(target_fl->l_start);
+ fl.l_len = tswap64(target_fl->l_len);
fl.l_pid = tswap32(target_fl->l_pid);
fl.l_sysid = tswap32(target_fl->l_sysid);
unlock_user_struct(target_fl, arg3, 0);
@@ -5682,8 +5699,8 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
return (-TARGET_EFAULT);
target_fl->l_type = tswap16(fl.l_type);
target_fl->l_whence = tswap16(fl.l_whence);
- target_fl->l_start = tswapal(fl.l_start);
- target_fl->l_len = tswapal(fl.l_len);
+ target_fl->l_start = tswap64(fl.l_start);
+ target_fl->l_len = tswap64(fl.l_len);
target_fl->l_pid = tswap32(fl.l_pid);
target_fl->l_sysid = tswap32(fl.l_sysid);
unlock_user_struct(target_fl, arg3, 1);
@@ -5694,8 +5711,8 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_F_SETLKW:
if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
return (-TARGET_EFAULT);
- fl.l_start = tswapal(target_fl->l_start);
- fl.l_len = tswapal(target_fl->l_len);
+ fl.l_start = tswap64(target_fl->l_start);
+ fl.l_len = tswap64(target_fl->l_len);
fl.l_pid = tswap32(target_fl->l_pid);
fl.l_type = tswap16(target_fl->l_type);
fl.l_whence = tswap16(target_fl->l_whence);
diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h
index 8a92403..eb804b3 100644
--- a/bsd-user/syscall_defs.h
+++ b/bsd-user/syscall_defs.h
@@ -132,8 +132,8 @@
#define TARGET_TRAP_TRACE (2) /* process trace trap */
struct target_rlimit {
- abi_ulong rlim_cur;
- abi_ulong rlim_max;
+ uint64_t rlim_cur;
+ uint64_t rlim_max;
};
#if defined(TARGET_ALPHA)
@@ -203,8 +203,8 @@ struct target_pollfd {
#include "openbsd/syscall_nr.h"
struct target_flock {
- abi_long l_start;
- abi_long l_len;
+ int64_t l_start;
+ int64_t l_len;
int32_t l_pid;
int16_t l_type;
int16_t l_whence;
@@ -260,19 +260,29 @@ __target_cmsg_nxthdr (struct target_msghdr *__mhdr,
}
struct target_sockaddr {
- uint16_t sa_family;
+ uint8_t sa_len;
+ uint8_t sa_family;
uint8_t sa_data[14];
-};
+} QEMU_PACKED;
struct target_in_addr {
uint32_t s_addr; /* big endian */
};
+/*
+ * FreeBSD/{arm, mips} uses a 64bits time_t, even in 32bits mode,
+ * so we have to add a special case here.
+ */
+#if defined(TARGET_ARM) || defined(TARGET_MIPS)
+typedef int64_t target_freebsd_time_t;
+#else
+typedef abi_long target_freebsd_time_t;
+#endif
struct target_timeval {
- abi_long tv_sec;
+ target_freebsd_time_t tv_sec;
abi_long tv_usec;
-};
+} QEMU_PACKED;
typedef abi_long target_clock_t;
@@ -304,21 +314,13 @@ struct target_kevent {
abi_ulong udata;
} __packed;
-/*
- * FreeBSD/arm uses a 64bits time_t, even in 32bits mode, so we have to
- * add a special case here.
- */
-#if defined(TARGET_ARM)
-typedef uint64_t target_freebsd_time_t;
-#else
-typedef long target_freebsd_time_t;
-#endif
struct target_freebsd_timespec {
target_freebsd_time_t tv_sec; /* seconds */
abi_long tv_nsec; /* and nanoseconds */
} __packed;
+/* XXX We have target_*_timeval defined twice. */
struct target_freebsd_timeval {
target_freebsd_time_t tv_sec;
abi_long tv_usec;
@@ -672,7 +674,7 @@ struct target_statfs {
uint64_t f_asyncreads; /* count of async reads since mount */
uint64_t f_spare[10]; /* unused spare */
uint32_t f_namemax; /* maximum filename length */
- uid_t f_owner; /* user that mounted the filesystem */
+ uint32_t f_owner; /* user that mounted the filesystem */
target_fsid_t f_fsid; /* filesystem id */
char f_charspare[80]; /* spare string space */
char f_fstypename[TARGET_MFSNAMELEN]; /* filesys type name */
diff --git a/bsd-user/x86_64/target_signal.h b/bsd-user/x86_64/target_signal.h
index a14e0b9..72df2f0 100644
--- a/bsd-user/x86_64/target_signal.h
+++ b/bsd-user/x86_64/target_signal.h
@@ -3,7 +3,8 @@
#include "cpu.h"
-static inline abi_ulong get_sp_from_cpustate(CPUX86State *state)
+static inline abi_ulong
+get_sp_from_cpustate(CPUX86State *state)
{
return state->regs[R_ESP];
}
@@ -26,18 +27,26 @@ typedef struct target_ucontext {
int32_t __spare__[4];
} target_ucontext_t;
-static inline int
+static inline abi_long
get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
{
fprintf(stderr, "x86_64 doesn't have support for get_mcontext()\n");
return (-TARGET_ENOSYS);
}
-static inline int
+static inline abi_long
set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags)
{
fprintf(stderr, "x86_64 doesn't have support for set_mcontext()\n");
return (-TARGET_ENOSYS);
}
+static inline abi_long
+get_ucontext_sigreturn(CPUArchState *regs, abi_ulong sf_addr,
+ target_ucontext_t **ucontext, void **locked_addr)
+{
+ fprintf(stderr, "x86_64 doesn't have support for do_sigreturn()\n");
+ return (-TARGET_ENOSYS);
+}
+
#endif /* TARGET_SIGNAL_H */