- 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
321 lines
9.2 KiB
Text
321 lines
9.2 KiB
Text
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;
|
|
|