--- oldqemu-1.3.0/bsd-user/syscall.c 2012-12-13 23:51:09.000000000 +0100 +++ qemu-1.3.0/bsd-user/syscall.c 2012-12-13 23:46:55.000000000 +0100 @@ -258,6 +258,16 @@ static abi_long do_freebsd_sysarch(void #ifdef TARGET_ARM static abi_long do_freebsd_sysarch(void *env, int op, abi_ulong parms) { + abi_ulong val; + + switch (op) { + case TARGET_FREEBSD_ARM_SET_TP: + if (get_user(val, parms, abi_ulong)) + return -TARGET_EINVAL; + cpu_set_tls(env, val); + return 0; + } + return -TARGET_EINVAL; } #endif --- oldqemu-1.3.0/bsd-user/elfload.c 2012-12-13 23:51:09.000000000 +0100 +++ qemu-1.3.0/bsd-user/elfload.c 2012-12-13 23:50:14.000000000 +0100 @@ -948,10 +948,8 @@ static abi_ulong create_elf_tables(abi_u * Force 16 byte _final_ alignment here for generality. */ sp = sp &~ (abi_ulong)15; -#ifdef __FreeBSD__ - size = 0; -#else size = (DLINFO_ITEMS + 1) * 2; +#ifndef __FreeBSD__ if (k_platform) size += 2; #ifdef DLINFO_ARCH_ITEMS @@ -964,7 +962,6 @@ static abi_ulong create_elf_tables(abi_u if (size & 15) sp -= 16 - (size & 15); -#ifndef __FreeBSD__ /* This is correct because Linux defines * elf_addr_t as Elf32_Off / Elf64_Off */ @@ -989,8 +986,10 @@ static abi_ulong create_elf_tables(abi_u NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); +#ifndef __FreeBSD__ if (k_platform) NEW_AUX_ENT(AT_PLATFORM, u_platform); +#endif #ifdef ARCH_DLINFO /* * ARCH_DLINFO must come last so platform specific code can enforce @@ -999,7 +998,6 @@ static abi_ulong create_elf_tables(abi_u ARCH_DLINFO; #endif #undef NEW_AUX_ENT -#endif /* ! __FreeBSD__ */ sp = loader_build_argptr(envc, argc, sp, p, !ibcs); return sp; --- oldqemu-1.3.0/bsd-user/main.c 2012-12-13 23:51:09.000000000 +0100 +++ qemu-1.3.0/bsd-user/main.c 2012-12-13 23:01:30.000000000 +0100 @@ -392,6 +392,84 @@ void cpu_loop(CPUX86State *env) #ifdef TARGET_ARM // #define DEBUG_ARM +static int do_strex(CPUARMState *env) +{ + uint32_t val; + int size; + int rc = 1; + int segv = 0; + uint32_t addr; + start_exclusive(); + addr = env->exclusive_addr; + if (addr != env->exclusive_test) { + goto fail; + } + size = env->exclusive_info & 0xf; + switch (size) { + case 0: + segv = get_user_u8(val, addr); + break; + case 1: + segv = get_user_u16(val, addr); + break; + case 2: + case 3: + segv = get_user_u32(val, addr); + break; + default: + abort(); + } + if (segv) { + env->cp15.c6_data = addr; + goto done; + } + if (val != env->exclusive_val) { + goto fail; + } + if (size == 3) { + segv = get_user_u32(val, addr + 4); + if (segv) { + env->cp15.c6_data = addr + 4; + goto done; + } + if (val != env->exclusive_high) { + goto fail; + } + } + val = env->regs[(env->exclusive_info >> 8) & 0xf]; + switch (size) { + case 0: + segv = put_user_u8(val, addr); + break; + case 1: + segv = put_user_u16(val, addr); + break; + case 2: + case 3: + segv = put_user_u32(val, addr); + break; + } + if (segv) { + env->cp15.c6_data = addr; + goto done; + } + if (size == 3) { + val = env->regs[(env->exclusive_info >> 12) & 0xf]; + segv = put_user_u32(val, addr + 4); + if (segv) { + env->cp15.c6_data = addr + 4; + goto done; + } + } + rc = 0; +fail: + env->regs[15] += 4; + env->regs[(env->exclusive_info >> 4) & 0xf] = rc; +done: + end_exclusive(); + return segv; +} + void cpu_loop(CPUARMState *env) { int trapnr; @@ -622,6 +700,7 @@ void cpu_loop(CPUARMState *env) if (do_kernel_trap(env)) goto error; break; +#endif case EXCP_STREX: if (do_strex(env)) { addr = env->cp15.c6_data; @@ -629,7 +708,6 @@ void cpu_loop(CPUARMState *env) } break; error: -#endif default: fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); --- oldqemu-1.3.0/bsd-user/arm/syscall.h 2012-12-13 23:51:09.000000000 +0100 +++ qemu-1.3.0/bsd-user/arm/syscall.h 2012-12-13 23:45:22.000000000 +0100 @@ -21,3 +21,5 @@ struct target_pt_regs { #define ARM_r0 uregs[0] #define ARM_SYSCALL_BASE 0 /* XXX: FreeBSD only */ + +#define TARGET_FREEBSD_ARM_SET_TP 2