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 @@ -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 */