This is based on cognet's arm-bsd-user patches, http://www.ci0.org/qemu-bapt.tar.gz which I fixed to run a static echo executable which he also built: http://www.ci0.org/arm-binaries-2nox.tar.gz so now probably only syscall handling and fixes for threading are still missing, the same as for the other bsd-user targets. Help with that welcome... :) nox@FreeBSD.org Index: Makefile =================================================================== RCS file: /home/pcvs/ports/emulators/qemu-devel/Makefile,v retrieving revision 1.142 diff -u -p -r1.142 Makefile --- Makefile 27 Jun 2012 17:27:39 -0000 1.142 +++ Makefile 13 Jul 2012 15:49:33 -0000 @@ -6,19 +6,18 @@ # PORTNAME= qemu -PORTVERSION= 1.1.0 +PORTVERSION= 1.1.1 CATEGORIES= emulators MASTER_SITES= http://wiki.qemu.org/download/:release \ LOCAL/nox:snapshot PKGNAMESUFFIX= -devel -DISTFILES= ${DISTNAME}${EXTRACT_SUFX}:release +DISTFILES= ${DISTNAME}.tar.bz2:release DIST_SUBDIR= qemu/${PORTVERSION} MAINTAINER= nox@FreeBSD.org COMMENT= QEMU CPU Emulator - development version HAS_CONFIGURE= yes -USE_BZIP2= yes USE_GMAKE= yes USE_PERL5_BUILD= yes USE_PYTHON_BUILD= yes @@ -53,7 +52,7 @@ OPTIONS_DEFAULT=SDL OPENGL GNUTLS SASL J .include CONFIGURE_ARGS+= --extra-ldflags=-L${LOCALBASE}/lib -PORTDOCS= docs qemu-doc.html qemu-tech.html +PORTDOCS= docs qemu-doc.html qemu-tech.html qmp-commands.txt # XXX this fixes build with clang but --enable-tcg-interpreter that's # needed to avoid global register usage that clang doesn't support @@ -65,7 +64,7 @@ CLANG_CFLAGS_AS+= -no-integrated-as .if ${PORT_OPTIONS:MX86_TARGETS} .if ${PORT_OPTIONS:MBSD_USER} -CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user +CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu,i386-bsd-user,x86_64-bsd-user,sparc-bsd-user,sparc64-bsd-user,arm-bsd-user .else CONFIGURE_ARGS+= --target-list=i386-softmmu,x86_64-softmmu .endif Index: distinfo =================================================================== RCS file: /home/pcvs/ports/emulators/qemu-devel/distinfo,v retrieving revision 1.64 diff -u -p -r1.64 distinfo --- distinfo 9 Jun 2012 16:19:05 -0000 1.64 +++ distinfo 13 Jul 2012 15:49:33 -0000 @@ -1,2 +1,2 @@ -SHA256 (qemu/1.1.0/qemu-1.1.0.tar.bz2) = 927f498eff8dce2334de9338cae9e3a7c63bd472c85451235c45de5029140fc0 -SIZE (qemu/1.1.0/qemu-1.1.0.tar.bz2) = 9629317 +SHA256 (qemu/1.1.1/qemu-1.1.1.tar.bz2) = 004a3032b504e70174c504d6c156b1ec3445abd9913602af0d7a5ac0703ddf5c +SIZE (qemu/1.1.1/qemu-1.1.1.tar.bz2) = 11712524 Index: pkg-plist =================================================================== RCS file: /home/pcvs/ports/emulators/qemu-devel/pkg-plist,v retrieving revision 1.37 diff -u -p -r1.37 pkg-plist --- pkg-plist 27 Jun 2012 17:27:39 -0000 1.37 +++ pkg-plist 13 Jul 2012 15:49:33 -0000 @@ -22,6 +22,7 @@ bin/qemu-system-i386 %%NONX86%%bin/qemu-system-sh4eb %%NONX86%%bin/qemu-system-sparc %%NONX86%%bin/qemu-system-sparc64 +%%BSD_USER%%bin/qemu-arm %%BSD_USER%%bin/qemu-i386 %%BSD_USER%%bin/qemu-sparc %%BSD_USER%%bin/qemu-sparc64 Index: files/patch-Makefile =================================================================== RCS file: /home/pcvs/ports/emulators/qemu-devel/files/patch-Makefile,v retrieving revision 1.11 diff -u -p -r1.11 patch-Makefile --- files/patch-Makefile 9 Jun 2012 16:19:05 -0000 1.11 +++ files/patch-Makefile 13 Jul 2012 15:49:33 -0000 @@ -11,18 +11,18 @@ Index: qemu/Makefile ifdef CONFIG_VIRTFS DOCS+=fsdev/virtfs-proxy-helper.1 endif -@@ -269,8 +273,10 @@ BLOBS= - endif +@@ -270,8 +274,10 @@ endif install-doc: $(DOCS) -+ifndef NOPORTDOCS $(INSTALL_DIR) "$(DESTDIR)$(qemu_docdir)" ++ifndef NOPORTDOCS $(INSTALL_DATA) qemu-doc.html qemu-tech.html "$(DESTDIR)$(qemu_docdir)" + $(INSTALL_DATA) QMP/qmp-commands.txt "$(DESTDIR)$(qemu_docdir)" +endif ifdef CONFIG_POSIX $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1" $(INSTALL_DATA) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1" -@@ -289,8 +295,11 @@ install-confdir: +@@ -290,7 +296,10 @@ install-confdir: $(INSTALL_DIR) "$(DESTDIR)$(qemu_confdir)" install-sysconfig: install-datadir install-confdir @@ -34,4 +34,3 @@ Index: qemu/Makefile $(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/cpus-x86_64.conf "$(DESTDIR)$(qemu_datadir)" install: all $(if $(BUILD_DOCS),install-doc) install-sysconfig install-datadir - $(INSTALL_DIR) "$(DESTDIR)$(bindir)" Index: files/patch-configure =================================================================== RCS file: /home/pcvs/ports/emulators/qemu-devel/files/patch-configure,v retrieving revision 1.6 diff -u -p -r1.6 patch-configure --- files/patch-configure 9 Jun 2012 16:19:05 -0000 1.6 +++ files/patch-configure 13 Jul 2012 15:49:33 -0000 @@ -9,6 +9,14 @@ datadir="\${prefix}/share" qemu_docdir="\${prefix}/share/doc/qemu" bindir="\${prefix}/bin" +@@ -974,6 +974,7 @@ i386-bsd-user \ + x86_64-bsd-user \ + sparc-bsd-user \ + sparc64-bsd-user \ ++arm-bsd-user \ + " + fi + @@ -2511,15 +2511,18 @@ if compile_prog "" "" ; then fi Index: files/patch-z-arm-bsd-user-001 @@ -0,0 +1,376 @@ +--- 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 +@@ -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 */