diff --git a/bsd-user/arm/target_signal.h b/bsd-user/arm/target_signal.h index 6b7bb67..4a9e518 100644 --- a/bsd-user/arm/target_signal.h +++ b/bsd-user/arm/target_signal.h @@ -3,15 +3,57 @@ #include "cpu.h" -static inline abi_ulong get_sp_from_cpustate(CPUARMState *state) -{ - return state->regs[13]; -} +#define TARGET_REG_R0 0 +#define TARGET_REG_R1 1 +#define TARGET_REG_R2 2 +#define TARGET_REG_R3 3 +#define TARGET_REG_R4 4 +#define TARGET_REG_R5 5 +#define TARGET_REG_R6 6 +#define TARGET_REG_R7 7 +#define TARGET_REG_R8 8 +#define TARGET_REG_R9 9 +#define TARGET_REG_R10 10 +#define TARGET_REG_R11 11 +#define TARGET_REG_R12 12 +#define TARGET_REG_R13 13 +#define TARGET_REG_R14 14 +#define TARGET_REG_R15 15 +#define TARGET_REG_CPSR 16 +/* Convenience synonyms */ +#define TARGET_REG_FP TARGET_REG_R11 +#define TARGET_REG_SP TARGET_REG_R13 +#define TARGET_REG_LR TARGET_REG_R14 +#define TARGET_REG_PC TARGET_REG_R15 + +#define TARGET_GET_MC_CLEAR_RET 1 #define TARGET_MINSIGSTKSZ (1024 * 4) #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) +#define TARGET__NGREG 17 + +typedef struct { + uint32_t __fp_fpsr; + struct { + uint32_t __fp_exponent; + uint32_t __fp_mantissa_hi; + uint32_t __fp_mantissa_lo; + } __fp_fr[8]; +} target__fpregset_t; -typedef target_ulong target_mcontext_t; /* dummy */ +typedef struct { + uint32_t __vfp_fpscr; + uint32_t __vfp_fstmx[33]; + uint32_t __vfp_fpsid; +} target__vfpregset_t; + +typedef struct { + uint32_t __gregs[TARGET__NGREG]; + union { + target__fpregset_t __fpregs; + target__vfpregset_t __vfpregs; + } __fpu; +} target_mcontext_t; typedef struct target_ucontext { target_sigset_t uc_sigmask; @@ -22,18 +64,119 @@ typedef struct target_ucontext { int32_t __spare__[4]; } target_ucontext_t; +struct target_sigframe { + target_siginfo_t sf_si; /* saved siginfo */ + target_ucontext_t sf_uc; /* saved ucontext */ +}; + +#define TARGET_SZSIGCODE (8 * 4) + +/* Compare to arm/arm/locore.S ENTRY_NP(sigcode) */ +static inline int +install_sigtramp(abi_ulong offset, unsigned sigf_us, uint32_t sys_sigreturn) +{ + int i; + uint32_t sys_exit = TARGET_FREEBSD_NR_exit; + /* + * The code has to load r7 manually rather than using + * "ldr r7, =SYS_return to make sure the size of the + * code is correct. + */ + uint32_t sigtramp_code[] = { + /* 1 */ 0xE1A0000D, /* mov r0, sp */ + /* 2 */ 0xE59F700C, /* ldr r7, [pc, #12] */ + /* 3 */ 0xEF000000 + sys_sigreturn, /* swi (SYS_sigreturn) */ + /* 4 */ 0xE59F7008, /* ldr r7, [pc, #8] */ + /* 5 */ 0xEF000000 + sys_exit, /* swi (SYS_exit)*/ + /* 6 */ 0xEAFFFFFA, /* b . -16 */ + /* 7 */ sys_sigreturn, + /* 8 */ sys_exit + }; + + for(i = 0; i < 8; i++) + tswap32s(&sigtramp_code[i]); + + return(memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE)); +} + +static inline abi_ulong +get_sp_from_cpustate(CPUARMState *state) +{ + return state->regs[13]; /* sp */ +} + +/* + * Compare to arm/arm/machdep.c sendsig() + * Assumes that the target stack frame memory is locked. + */ +static inline int +set_sigtramp_args(CPUARMState *regs, int sig, struct target_sigframe *frame, + abi_ulong frame_addr, struct target_sigaction *ka) +{ + /* + * Arguments to signal handler: + * r0 = signal number + * r1 = siginfo pointer + * r2 = ucontext pointer + * r5 = ucontext pointer + * pc = signal handler pointer + * sp = sigframe struct pointer + * lr = sigtramp at base of user stack + */ + + regs->regs[0] = sig; + regs->regs[1] = frame_addr + + offsetof(struct target_sigframe, sf_si); + regs->regs[2] = frame_addr + + offsetof(struct target_sigframe, sf_uc); + + /* the trampoline uses r5 as the uc address */ + regs->regs[5] = frame_addr + + offsetof(struct target_sigframe, sf_uc); + regs->regs[TARGET_REG_PC] = ka->_sa_handler; + regs->regs[TARGET_REG_SP] = frame_addr; + regs->regs[TARGET_REG_LR] = TARGET_PS_STRINGS - TARGET_SZSIGCODE; + + return (0); +} + +/* Compare to arm/arm/machdep.c get_mcontext() */ static inline int -get_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags) +get_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int clear_ret) { - fprintf(stderr, "ARM doesn't have support for get_mcontext()\n"); - return (-TARGET_ENOSYS); + int i, err = 0; + uint32_t *gr = mcp->__gregs; + + + if (clear_ret & TARGET_GET_MC_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_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); + + return (err); } +/* Compare to arm/arm/machdep.c set_mcontext() */ static inline int -set_mcontext(CPUArchState *regs, target_mcontext_t *mcp, int flags) +set_mcontext(CPUARMState *regs, target_mcontext_t *mcp, int flags) { - fprintf(stderr, "ARM doesn't have support for set_mcontext()\n"); - return (-TARGET_ENOSYS); + int i, err = 0; + const uint32_t *gr = mcp->__gregs; + + 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]); + + return (err); } #endif /* TARGET_SIGNAL_H */ diff --git a/bsd-user/arm/target_vmparam.h b/bsd-user/arm/target_vmparam.h index 24dca00..bc50fbb 100644 --- a/bsd-user/arm/target_vmparam.h +++ b/bsd-user/arm/target_vmparam.h @@ -18,8 +18,6 @@ struct target_ps_strings { #define TARGET_PS_STRINGS (TARGET_USRSTACK - sizeof(struct target_ps_strings)) -#define TARGET_SZSIGCODE 0 - /* Make stack size large enough to hold everything. */ #define TARGET_STACK_SIZE ((x86_stack_size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) ? \ MAX_ARG_PAGES*TARGET_PAGE_SIZE : x86_stack_size) diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c index c2c3a65..76681e1 100644 --- a/bsd-user/elfload.c +++ b/bsd-user/elfload.c @@ -690,24 +690,6 @@ static abi_ulong copy_elf_strings(int argc,char ** argv, void **page, return p; } -#if defined(TARGET_MIPS64) -static inline int -install_sigtramp(abi_ulong offset, unsigned sigf_uc, unsigned syscall) -{ - int i; - uint32_t sigtramp_code[] = { - 0x67A40000 + sigf_uc, /* daddu $a0, $sp, (sigf_uc) */ - 0x24020000 + syscall, /* li $v0, (syscall) */ - 0x0000000C, /* syscall */ - 0x0000000D /* break */ - }; - - for(i = 0; i < 4; i++) - tswap32s(&sigtramp_code[i]); - - return (memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE)); -} -#endif static abi_ulong setup_arg_pages(abi_ulong p, struct bsd_binprm *bprm, struct image_info *info) diff --git a/bsd-user/mips64/target_signal.h b/bsd-user/mips64/target_signal.h index c592136..f657909 100644 --- a/bsd-user/mips64/target_signal.h +++ b/bsd-user/mips64/target_signal.h @@ -5,7 +5,6 @@ #define TARGET_MINSIGSTKSZ (512 * 4) #define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) -#define TARGET_SZSIGCODE 16 struct target_sigcontext { target_sigset_t sc_mask; /* signal mask to retstore */ @@ -56,9 +55,29 @@ get_sp_from_cpustate(CPUMIPSState *state) return state->active_tc.gpr[29]; } +#define TARGET_SZSIGCODE (4 * 4) + +/* Compare to mips/mips/locore.S sigcode() */ +static inline int +install_sigtramp(abi_ulong offset, unsigned sigf_uc, unsigned sys_sigreturn) +{ + int i; + uint32_t sigtramp_code[] = { + /* 1 */ 0x67A40000 + sigf_uc, /* daddu $a0, $sp, (sigf_uc) */ + /* 2 */ 0x24020000 + sys_sigreturn, /* li $v0, (sys_sigreturn) */ + /* 3 */ 0x0000000C, /* syscall */ + /* 4 */ 0x0000000D /* break */ + }; + + for(i = 0; i < 4; i++) + tswap32s(&sigtramp_code[i]); + + return (memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE)); +} + /* * Compare to mips/mips/pm_machdep.c sendsig() - * Assumes that "frame" memory is locked. + * Assumes that target stack frame memory is locked. */ static inline int set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame, @@ -67,6 +86,11 @@ set_sigtramp_args(CPUMIPSState *regs, int sig, struct target_sigframe *frame, /* frame->sf_si.si_addr = regs->CP0_BadVAddr; */ + /* MIPS only struct target_sigframe members: */ + frame->sf_signum = sig; + frame->sf_siginfo = (abi_ulong)&frame->sf_si; + frame->sf_ucontext = (abi_ulong)&frame->sf_uc; + /* * Arguments to signal handler: * a0 ($4) = signal number diff --git a/bsd-user/signal.c b/bsd-user/signal.c index 29e8e12..b04e874 100644 --- a/bsd-user/signal.c +++ b/bsd-user/signal.c @@ -613,7 +613,7 @@ do_sigaction(int sig, const struct target_sigaction *act, return (ret); } -#if defined(TARGET_MIPS64) /* || defined(TARGET_SPARC64) */ +#if defined(TARGET_MIPS64) || defined(TARGET_ARM) static inline abi_ulong get_sigframe(struct target_sigaction *ka, CPUArchState *regs, size_t frame_size) @@ -715,17 +715,8 @@ static void setup_frame(int sig, int code, struct target_sigaction *ka, } #endif - frame->sf_signum = sig; - frame->sf_siginfo = (abi_ulong)&frame->sf_si; - frame->sf_ucontext = (abi_ulong)&frame->sf_uc; - - } else { - frame->sf_signum = sig; - frame->sf_siginfo = 0; - frame->sf_ucontext = 0; } - if (set_sigtramp_args(regs, sig, frame, frame_addr, ka)) goto give_sigsegv;