mirror of
https://git.freebsd.org/ports.git
synced 2025-06-28 16:10:33 -04:00
- 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
388 lines
13 KiB
Text
388 lines
13 KiB
Text
--- a/bsd-user/elfload.c.orig
|
|
+++ b/bsd-user/elfload.c
|
|
@@ -190,6 +190,9 @@ static inline void init_thread(struct ta
|
|
if (infop->entry & 1)
|
|
regs->ARM_cpsr |= CPSR_T;
|
|
regs->ARM_pc = infop->entry & 0xfffffffe;
|
|
+ if (bsd_type == target_freebsd) {
|
|
+ regs->ARM_lr = infop->entry & 0xfffffffe;
|
|
+ }
|
|
regs->ARM_sp = infop->start_stack;
|
|
/* FIXME - what to for failure of get_user()? */
|
|
get_user_ual(regs->ARM_r2, stack + 8); /* envp */
|
|
--- a/bsd-user/main.c.orig
|
|
+++ b/bsd-user/main.c
|
|
@@ -389,6 +389,259 @@ void cpu_loop(CPUX86State *env)
|
|
}
|
|
#endif
|
|
|
|
+#ifdef TARGET_ARM
|
|
+// #define DEBUG_ARM
|
|
+
|
|
+void cpu_loop(CPUARMState *env)
|
|
+{
|
|
+ int trapnr;
|
|
+ unsigned int n, insn;
|
|
+ uint32_t addr;
|
|
+
|
|
+ for(;;) {
|
|
+#ifdef DEBUG_ARM
|
|
+ printf("CPU LOOPING\n");
|
|
+#endif
|
|
+ cpu_exec_start(env);
|
|
+#ifdef DEBUG_ARM
|
|
+ printf("EXECUTING...\n");
|
|
+#endif
|
|
+ trapnr = cpu_arm_exec(env);
|
|
+#ifdef DEBUG_ARM
|
|
+ printf("trapnr %d\n", trapnr);
|
|
+#endif
|
|
+ cpu_exec_end(env);
|
|
+ switch(trapnr) {
|
|
+ case EXCP_UDEF:
|
|
+ {
|
|
+#if 0
|
|
+ TaskState *ts = env->opaque;
|
|
+ uint32_t opcode;
|
|
+ int rc;
|
|
+
|
|
+ /* we handle the FPU emulation here, as Linux */
|
|
+ /* we get the opcode */
|
|
+ /* FIXME - what to do if get_user() fails? */
|
|
+ get_user_u32(opcode, env->regs[15]);
|
|
+
|
|
+ rc = EmulateAll(opcode, &ts->fpa, env);
|
|
+ if (rc == 0) { /* illegal instruction */
|
|
+ info.si_signo = SIGILL;
|
|
+ info.si_errno = 0;
|
|
+ info.si_code = TARGET_ILL_ILLOPN;
|
|
+ info._sifields._sigfault._addr = env->regs[15];
|
|
+ queue_signal(env, info.si_signo, &info);
|
|
+
|
|
+ } else if (rc < 0) { /* FP exception */
|
|
+ int arm_fpe=0;
|
|
+
|
|
+ /* translate softfloat flags to FPSR flags */
|
|
+ if (-rc & float_flag_invalid)
|
|
+ arm_fpe |= BIT_IOC;
|
|
+ if (-rc & float_flag_divbyzero)
|
|
+ arm_fpe |= BIT_DZC;
|
|
+ if (-rc & float_flag_overflow)
|
|
+ arm_fpe |= BIT_OFC;
|
|
+ if (-rc & float_flag_underflow)
|
|
+ arm_fpe |= BIT_UFC;
|
|
+ if (-rc & float_flag_inexact)
|
|
+ arm_fpe |= BIT_IXC;
|
|
+
|
|
+ FPSR fpsr = ts->fpa.fpsr;
|
|
+ //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe);
|
|
+
|
|
+ if (fpsr & (arm_fpe << 16)) { /* exception enabled? */
|
|
+ info.si_signo = SIGFPE;
|
|
+ info.si_errno = 0;
|
|
+
|
|
+ /* ordered by priority, least first */
|
|
+ if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES;
|
|
+ if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND;
|
|
+ if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF;
|
|
+ if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV;
|
|
+ if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV;
|
|
+
|
|
+ info._sifields._sigfault._addr = env->regs[15];
|
|
+ queue_signal(env, info.si_signo, &info);
|
|
+ } else {
|
|
+ env->regs[15] += 4;
|
|
+ }
|
|
+
|
|
+ /* accumulate unenabled exceptions */
|
|
+ if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC))
|
|
+ fpsr |= BIT_IXC;
|
|
+ if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC))
|
|
+ fpsr |= BIT_UFC;
|
|
+ if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC))
|
|
+ fpsr |= BIT_OFC;
|
|
+ if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC))
|
|
+ fpsr |= BIT_DZC;
|
|
+ if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC))
|
|
+ fpsr |= BIT_IOC;
|
|
+ ts->fpa.fpsr=fpsr;
|
|
+ } else { /* everything OK */
|
|
+ /* increment PC */
|
|
+ env->regs[15] += 4;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+ break;
|
|
+ case EXCP_SWI:
|
|
+ case EXCP_BKPT:
|
|
+ {
|
|
+ env->eabi = 1;
|
|
+ /* system call */
|
|
+ if (trapnr == EXCP_BKPT) {
|
|
+ if (env->thumb) {
|
|
+ /* FIXME - what to do if get_user() fails? */
|
|
+ get_user_u16(insn, env->regs[15]);
|
|
+ n = insn & 0xff;
|
|
+ env->regs[15] += 2;
|
|
+ } else {
|
|
+ /* FIXME - what to do if get_user() fails? */
|
|
+ get_user_u32(insn, env->regs[15]);
|
|
+ n = (insn & 0xf) | ((insn >> 4) & 0xff0);
|
|
+ env->regs[15] += 4;
|
|
+ }
|
|
+ } else {
|
|
+ if (env->thumb) {
|
|
+ /* FIXME - what to do if get_user() fails? */
|
|
+ get_user_u16(insn, env->regs[15] - 2);
|
|
+ n = insn & 0xff;
|
|
+ } else {
|
|
+ /* FIXME - what to do if get_user() fails? */
|
|
+ get_user_u32(insn, env->regs[15] - 4);
|
|
+ n = insn & 0xffffff;
|
|
+ }
|
|
+ }
|
|
+
|
|
+#ifdef DEBUG_ARM
|
|
+ printf("AVANT CALL %d\n", n);
|
|
+#endif
|
|
+ if (bsd_type == target_freebsd) {
|
|
+ int ret;
|
|
+ abi_ulong params = get_sp_from_cpustate(env);
|
|
+ int32_t syscall_nr = n;
|
|
+ int32_t arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8;
|
|
+
|
|
+#if 0 // XXX FIXME
|
|
+ if (syscall_nr == TARGET_FREEBSD_NR_syscall) {
|
|
+ get_user_s32(syscall_nr, params);
|
|
+ params += sizeof(int32_t);
|
|
+ } else if (syscall_nr == TARGET_FREEBSD_NR___syscall) {
|
|
+ get_user_s32(syscall_nr, params);
|
|
+ params += sizeof(int64_t);
|
|
+ }
|
|
+#endif
|
|
+ arg1 = env->regs[0];
|
|
+ arg2 = env->regs[1];
|
|
+ arg3 = env->regs[2];
|
|
+ arg4 = env->regs[3];
|
|
+ get_user_s32(arg5, params);
|
|
+ params += sizeof(int32_t);
|
|
+ get_user_s32(arg6, params);
|
|
+ params += sizeof(int32_t);
|
|
+ get_user_s32(arg7, params);
|
|
+ params += sizeof(int32_t);
|
|
+ get_user_s32(arg8, params);
|
|
+ ret = do_freebsd_syscall(env,
|
|
+ syscall_nr,
|
|
+ arg1,
|
|
+ arg2,
|
|
+ arg3,
|
|
+ arg4,
|
|
+ arg5,
|
|
+ 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;
|
|
+ }
|
|
+ } else {
|
|
+ // XXX is this correct?
|
|
+ env->regs[0] = do_openbsd_syscall(env,
|
|
+ n,
|
|
+ env->regs[0],
|
|
+ env->regs[1],
|
|
+ env->regs[2],
|
|
+ env->regs[3],
|
|
+ env->regs[4],
|
|
+ env->regs[5]);
|
|
+ }
|
|
+#ifdef DEBUG_ARM
|
|
+ printf("APRES CALL\n");
|
|
+#endif
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+ case EXCP_INTERRUPT:
|
|
+ /* just indicate that signals should be handled asap */
|
|
+ break;
|
|
+ case EXCP_PREFETCH_ABORT:
|
|
+ addr = env->cp15.c6_insn;
|
|
+ goto do_segv;
|
|
+ case EXCP_DATA_ABORT:
|
|
+ addr = env->cp15.c6_data;
|
|
+ do_segv:
|
|
+ {
|
|
+#if 0
|
|
+#
|
|
+ info.si_signo = SIGSEGV;
|
|
+ info.si_errno = 0;
|
|
+ /* XXX: check env->error_code */
|
|
+ info.si_code = TARGET_SEGV_MAPERR;
|
|
+ info._sifields._sigfault._addr = addr;
|
|
+ queue_signal(env, info.si_signo, &info);
|
|
+#endif
|
|
+ }
|
|
+ break;
|
|
+ case EXCP_DEBUG:
|
|
+ {
|
|
+ int sig;
|
|
+
|
|
+ sig = gdb_handlesig (env, TARGET_SIGTRAP);
|
|
+ if (sig)
|
|
+ {
|
|
+#if 0
|
|
+ info.si_signo = sig;
|
|
+ info.si_errno = 0;
|
|
+ info.si_code = TARGET_TRAP_BRKPT;
|
|
+ queue_signal(env, info.si_signo, &info);
|
|
+#endif
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+#if 0
|
|
+ case EXCP_KERNEL_TRAP:
|
|
+ if (do_kernel_trap(env))
|
|
+ goto error;
|
|
+ break;
|
|
+ case EXCP_STREX:
|
|
+ if (do_strex(env)) {
|
|
+ addr = env->cp15.c6_data;
|
|
+ goto do_segv;
|
|
+ }
|
|
+ break;
|
|
+ error:
|
|
+#endif
|
|
+ default:
|
|
+ fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
|
+ trapnr);
|
|
+ cpu_dump_state(env, stderr, fprintf, 0);
|
|
+ abort();
|
|
+ }
|
|
+ process_pending_signals(env);
|
|
+ }
|
|
+}
|
|
+
|
|
+#endif
|
|
+
|
|
#ifdef TARGET_SPARC
|
|
#define SPARC64_STACK_BIAS 2047
|
|
|
|
@@ -1133,6 +1386,14 @@ int main(int argc, char **argv)
|
|
for(i = 0; i < 8; i++)
|
|
env->regwptr[i] = regs->u_regs[i + 8];
|
|
}
|
|
+#elif defined(TARGET_ARM)
|
|
+ {
|
|
+ int i;
|
|
+ cpsr_write(env, regs->uregs[16], 0xffffffff);
|
|
+ for (i = 0; i < 16; i++) {
|
|
+ env->regs[i] = regs->uregs[i];
|
|
+ }
|
|
+ }
|
|
#else
|
|
#error unsupported target CPU
|
|
#endif
|
|
--- a/bsd-user/syscall.c.orig
|
|
+++ b/bsd-user/syscall.c
|
|
@@ -96,6 +96,11 @@ static abi_long do_obreak(abi_ulong new_
|
|
return 0;
|
|
}
|
|
|
|
+abi_long do_brk(abi_ulong new_brk)
|
|
+{
|
|
+ return do_obreak(new_brk);
|
|
+}
|
|
+
|
|
#if defined(TARGET_I386)
|
|
static abi_long do_freebsd_sysarch(CPUX86State *env, int op, abi_ulong parms)
|
|
{
|
|
@@ -157,6 +161,12 @@ static abi_long do_freebsd_sysarch(void
|
|
}
|
|
#endif
|
|
|
|
+#ifdef TARGET_ARM
|
|
+static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms)
|
|
+{
|
|
+ return -TARGET_EINVAL;
|
|
+}
|
|
+#endif
|
|
#ifdef __FreeBSD__
|
|
/*
|
|
* XXX this uses the undocumented oidfmt interface to find the kind of
|
|
@@ -215,6 +225,7 @@ static int sysctl_oldcvt(void *holdp, si
|
|
case CTLTYPE_QUAD:
|
|
#else
|
|
case CTLTYPE_U64:
|
|
+ case CTLTYPE_S64:
|
|
#endif
|
|
*(uint64_t *)holdp = tswap64(*(uint64_t *)holdp);
|
|
break;
|
|
@@ -380,6 +391,9 @@ abi_long do_freebsd_syscall(void *cpu_en
|
|
arg5,
|
|
arg6));
|
|
break;
|
|
+ case TARGET_FREEBSD_NR_munmap:
|
|
+ ret = get_errno(target_munmap(arg1, arg2));
|
|
+ break;
|
|
case TARGET_FREEBSD_NR_mprotect:
|
|
ret = get_errno(target_mprotect(arg1, arg2, arg3));
|
|
break;
|
|
--- /dev/null
|
|
+++ b/default-configs/arm-bsd-user.mak
|
|
@@ -0,0 +1,3 @@
|
|
+# Default configuration for arm-bsd-user
|
|
+
|
|
+CONFIG_GDBSTUB_XML=y
|
|
--- /dev/null
|
|
+++ b/bsd-user/arm/syscall.h
|
|
@@ -0,0 +1,23 @@
|
|
+struct target_pt_regs {
|
|
+ abi_long uregs[15];
|
|
+};
|
|
+
|
|
+#define ARM_cpsr uregs[16]
|
|
+#define ARM_pc uregs[15]
|
|
+#define ARM_lr uregs[14]
|
|
+#define ARM_sp uregs[13]
|
|
+#define ARM_ip uregs[12]
|
|
+#define ARM_fp uregs[11]
|
|
+#define ARM_r10 uregs[10]
|
|
+#define ARM_r9 uregs[9]
|
|
+#define ARM_r8 uregs[8]
|
|
+#define ARM_r7 uregs[7]
|
|
+#define ARM_r6 uregs[6]
|
|
+#define ARM_r5 uregs[5]
|
|
+#define ARM_r4 uregs[4]
|
|
+#define ARM_r3 uregs[3]
|
|
+#define ARM_r2 uregs[2]
|
|
+#define ARM_r1 uregs[1]
|
|
+#define ARM_r0 uregs[0]
|
|
+
|
|
+#define ARM_SYSCALL_BASE 0 /* XXX: FreeBSD only */
|
|
--- /dev/null
|
|
+++ b/bsd-user/arm/target_signal.h
|
|
@@ -0,0 +1,19 @@
|
|
+#ifndef TARGET_SIGNAL_H
|
|
+#define TARGET_SIGNAL_H
|
|
+
|
|
+#include "cpu.h"
|
|
+
|
|
+/* this struct defines a stack used during syscall handling */
|
|
+
|
|
+typedef struct target_sigaltstack {
|
|
+ abi_ulong ss_sp;
|
|
+ abi_long ss_flags;
|
|
+ abi_ulong ss_size;
|
|
+} target_stack_t;
|
|
+
|
|
+static inline abi_ulong get_sp_from_cpustate(CPUARMState *state)
|
|
+{
|
|
+ return state->regs[13];
|
|
+}
|
|
+
|
|
+#endif /* TARGET_SIGNAL_H */
|