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