diff options
author | Richard Purdie <rpurdie@rpsys.net> | 2008-01-28 15:06:05 +0000 |
---|---|---|
committer | Richard Purdie <rpurdie@rpsys.net> | 2008-01-28 15:06:05 +0000 |
commit | a1c5c1c76a4f7077b7ebebbc9d663907fe48ff23 (patch) | |
tree | 79f739a05ea964572a1d43910ebc07ab6e69db12 /packages/qemu/qemu-0.9.1/qemu-0.9.0-nptl-update.patch | |
parent | d76686de147df8b1e8d20a1320d7b5ba8ad94dbb (diff) | |
parent | 2a7d6f00f3b73eef0a1e83829fabc79577ec60af (diff) |
merge of 'd13e860cc99eb6e7165589bb5b3efcdc273ae032'
and 'dc89094b528d67f441ec460b0a314a2ff6ccbb98'
Diffstat (limited to 'packages/qemu/qemu-0.9.1/qemu-0.9.0-nptl-update.patch')
-rw-r--r-- | packages/qemu/qemu-0.9.1/qemu-0.9.0-nptl-update.patch | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/packages/qemu/qemu-0.9.1/qemu-0.9.0-nptl-update.patch b/packages/qemu/qemu-0.9.1/qemu-0.9.0-nptl-update.patch new file mode 100644 index 0000000000..ebc996e873 --- /dev/null +++ b/packages/qemu/qemu-0.9.1/qemu-0.9.0-nptl-update.patch @@ -0,0 +1,219 @@ +--- + linux-user/main.c | 7 ++- + linux-user/syscall.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 111 insertions(+), 10 deletions(-) + +Index: qemu/linux-user/main.c +=================================================================== +--- qemu.orig/linux-user/main.c 2007-12-03 19:34:09.000000000 +0000 ++++ qemu/linux-user/main.c 2007-12-03 23:44:45.000000000 +0000 +@@ -391,7 +391,7 @@ do_kernel_trap(CPUARMState *env) + cpu_unlock(); + break; + case 0xffff0fe0: /* __kernel_get_tls */ +- env->regs[0] = env->cp15.c13_tls; ++ env->regs[0] = env->cp15.c13_tls2; + break; + default: + return 1; +@@ -2037,6 +2037,11 @@ int main(int argc, char **argv) + int drop_ld_preload = 0, environ_count = 0; + char **target_environ, **wrk, **dst; + ++ char *assume_kernel = getenv("QEMU_ASSUME_KERNEL"); ++ ++ if (assume_kernel) ++ setenv("LD_ASSUME_KERNEL", assume_kernel, 1); ++ + if (argc <= 1) + usage(); + +Index: qemu/linux-user/syscall.c +=================================================================== +--- qemu.orig/linux-user/syscall.c 2007-12-03 19:34:09.000000000 +0000 ++++ qemu/linux-user/syscall.c 2007-12-03 23:46:54.000000000 +0000 +@@ -61,6 +61,7 @@ + #define tchars host_tchars /* same as target */ + #define ltchars host_ltchars /* same as target */ + ++#include <linux/futex.h> + #include <linux/termios.h> + #include <linux/unistd.h> + #include <linux/utsname.h> +@@ -2694,7 +2695,6 @@ abi_long do_arch_prctl(CPUX86State *env, + return 0; + } + #endif +- + #endif /* defined(TARGET_I386) */ + + /* this stack is the equivalent of the kernel stack associated with a +@@ -2729,16 +2729,19 @@ int do_fork(CPUState *env, unsigned int + TaskState *ts; + uint8_t *new_stack; + CPUState *new_env; +- ++#if defined(TARGET_I386) ++ uint64_t *new_gdt_table; ++#endif + #ifdef USE_NPTL + unsigned int nptl_flags; + + if (flags & CLONE_PARENT_SETTID) + *parent_tidptr = gettid(); + #endif +- + if (flags & CLONE_VM) { + ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE); ++ if (!ts) ++ return -ENOMEM; + memset(ts, 0, sizeof(TaskState)); + new_stack = ts->stack; + ts->used = 1; +@@ -2750,6 +2753,29 @@ int do_fork(CPUState *env, unsigned int + #if defined(TARGET_I386) + if (!newsp) + newsp = env->regs[R_ESP]; ++ new_gdt_table = malloc(9 * 8); ++ if (!new_gdt_table) { ++ free(new_env); ++ return -ENOMEM; ++ } ++ /* Copy main GDT table from parent, but clear TLS entries */ ++ memcpy(new_gdt_table, g2h(env->gdt.base), 6 * 8); ++ memset(&new_gdt_table[6], 0, 3 * 8); ++ new_env->gdt.base = h2g(new_gdt_table); ++ if (flags & 0x00080000 /* CLONE_SETTLS */) { ++ ret = do_set_thread_area(new_env, new_env->regs[R_ESI]); ++ if (ret) { ++ free(new_gdt_table); ++ free(new_env); ++ return ret; ++ } ++ } ++ cpu_x86_load_seg(env, R_CS, new_env->regs[R_CS]); ++ cpu_x86_load_seg(env, R_DS, new_env->regs[R_DS]); ++ cpu_x86_load_seg(env, R_ES, new_env->regs[R_ES]); ++ cpu_x86_load_seg(env, R_SS, new_env->regs[R_SS]); ++ cpu_x86_load_seg(env, R_FS, new_env->regs[R_FS]); ++ cpu_x86_load_seg(env, R_GS, new_env->regs[R_GS]); + new_env->regs[R_ESP] = newsp; + new_env->regs[R_EAX] = 0; + #elif defined(TARGET_ARM) +@@ -3121,6 +3147,68 @@ static inline abi_long host_to_target_ti + unlock_user_struct(target_ts, target_addr, 1); + } + ++static long do_futex(target_ulong uaddr, int op, uint32_t val, ++ target_ulong utime, target_ulong uaddr2, ++ uint32_t val3) ++{ ++ struct timespec host_utime; ++ unsigned long val2 = utime; ++ ++ if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) { ++ target_to_host_timespec(&host_utime, utime); ++ val2 = (unsigned long)&host_utime; ++ } ++ ++#ifdef BSWAP_NEEDED ++ switch(op) { ++ case FUTEX_CMP_REQUEUE: ++ val3 = tswap32(val3); ++ case FUTEX_REQUEUE: ++ val2 = tswap32(val2); ++ case FUTEX_WAIT: ++ case FUTEX_WAKE: ++ val = tswap32(val); ++ case FUTEX_LOCK_PI: /* This one's icky, but comes out OK */ ++ case FUTEX_UNLOCK_PI: ++ break; ++ default: ++ gemu_log("qemu: Unsupported futex op %d\n", op); ++ return -ENOSYS; ++ } ++#if 0 /* No, it's worse than this */ ++ if (op == FUTEX_WAKE_OP) { ++ /* Need to munge the secondary operation (val3) */ ++ val3 = tswap32(val3); ++ int op2 = (val3 >> 28) & 7; ++ int cmp = (val3 >> 24) & 15; ++ int oparg = (val3 << 8) >> 20; ++ int cmparg = (val3 << 20) >> 20; ++ int shift = val3 & (FUTEX_OP_OPARG_SHIFT << 28); ++ ++ if (shift) ++ oparg = (oparg & 7) + 24 - (oparg & 24); ++ else oparg = ++ if (op2 == FUTEX_OP_ADD) { ++ gemu_log("qemu: Unsupported wrong-endian FUTEX_OP_ADD\n"); ++ return -ENOSYS; ++ } ++ if (cmparg == FUTEX_OP_CMP_LT || cmparg == FUTEX_OP_CMP_GE || ++ cmparg == FUTEX_OP_CMP_LE || cmparg == FUTEX_OP_CMP_GT) { ++ gemu_log("qemu: Unsupported wrong-endian futex cmparg %d\n", cmparg); ++ return -ENOSYS; ++ } ++ val3 = shift | (op2<<28) | (cmp<<24) | (oparg<<12) | cmparg; ++ } ++#endif ++#endif ++ return syscall(__NR_futex, g2h(uaddr), op, val, val2, g2h(uaddr2), val3); ++} ++ ++int do_set_tid_address(target_ulong tidptr) ++{ ++ return syscall(__NR_set_tid_address, g2h(tidptr)); ++} ++ + /* do_syscall() should always have a single exit point at the end so + that actions, such as logging of syscall results, can be performed. + All errnos that do_syscall() returns must be -TARGET_<errcode>. */ +@@ -3145,7 +3233,7 @@ abi_long do_syscall(void *cpu_env, int n + _mcleanup(); + #endif + gdb_exit(cpu_env, arg1); +- /* XXX: should free thread stack and CPU env */ ++ /* XXX: should free thread stack, GDT and CPU env */ + _exit(arg1); + ret = 0; /* avoid warning */ + break; +@@ -5569,6 +5657,9 @@ abi_long do_syscall(void *cpu_env, int n + #elif defined(TARGET_I386) && defined(TARGET_ABI32) + ret = do_set_thread_area(cpu_env, arg1); + break; ++#elif TARGET_i386 ++ ret = get_errno(do_set_thread_area(cpu_env, arg1)); ++ break; + #else + goto unimplemented_nowarn; + #endif +@@ -5586,6 +5677,16 @@ abi_long do_syscall(void *cpu_env, int n + goto unimplemented_nowarn; + #endif + ++#ifdef TARGET_NR_futex ++ case TARGET_NR_futex: ++ ret = get_errno(do_futex(arg1, arg2, arg3, arg4, arg5, arg6)); ++ break; ++#endif ++#ifdef TARGET_NR_set_robust_list ++ case TARGET_NR_set_robust_list: ++ goto unimplemented_nowarn; ++#endif ++ + #ifdef TARGET_NR_clock_gettime + case TARGET_NR_clock_gettime: + { +@@ -5627,11 +5728,6 @@ abi_long do_syscall(void *cpu_env, int n + break; + #endif + +-#ifdef TARGET_NR_set_robust_list +- case TARGET_NR_set_robust_list: +- goto unimplemented_nowarn; +-#endif +- + #if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) + case TARGET_NR_utimensat: + { |