ports/emulators/qemu-devel/files/patch-z-arm-bsd-user-001
Juergen Lock 45aa9370f0 - Update net/usbredir to 0.6 .
- 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
2013-03-29 17:40:38 +00:00

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