Message ID | 1250785143-24969-1-git-send-email-uli@suse.de |
---|---|
State | Superseded |
Headers | show |
On Thu, Aug 20, 2009 at 06:19:03PM +0200, Ulrich Hecht wrote: > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > - if (nptl_flags & CLONE_SETTLS) > + if (nptl_flags & CLONE_SETTLS) { > +#if defined(TARGET_I386) && defined(TARGET_ABI32) > + do_set_thread_area(new_env, newtls); > + cpu_x86_load_seg(new_env, R_GS, new_env->segs[R_GS].selector); > +#else > cpu_set_tls (new_env, newtls); > +#endif > + } Why not just stick things in cpu_set_tls in target-i386/cpu.h like so: #if defined(TARGET-I386) && defined(TARGET_ABI32) static inline void cpu_set_tls(CPUState *env, target_ulong newtls) { do_set_thread_area(env, newtls); cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector); } #endif Less duplicated code and fewer #ifdefs that way and it's still clear that x86-64 linux-user emulation doesn't support NPTL. -Nathan
On Thursday 20 August 2009, Nathan Froyd wrote: > Why not just stick things in cpu_set_tls in target-i386/cpu.h like so: > > #if defined(TARGET-I386) && defined(TARGET_ABI32) > static inline void cpu_set_tls(CPUState *env, target_ulong newtls) > { > do_set_thread_area(env, newtls); > cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector); > } > #endif > > Less duplicated code and fewer #ifdefs that way and it's still clear > that x86-64 linux-user emulation doesn't support NPTL. do_set_thread_area() is declared static in syscall.c, so you would have to unstaticize it, create a prototype somewhere (where?), and you would introduce a dependency between the CPU emulation and the userspace emulation. These problems are all unique to the i386 architecture which doesn't get away with just setting a CPU register like all the others. (Except maybe x86-64, but I don't know how TLS is implemented there.) My solution may not look as clean, but it sidesteps all this, which I thought made it worthwhile to special-case i386 in syscall.c. CU Uli
On Fri, Aug 21, 2009 at 12:10:31PM +0200, Ulrich Hecht wrote: > On Thursday 20 August 2009, Nathan Froyd wrote: > > Why not just stick things in cpu_set_tls in target-i386/cpu.h like so: > > > > #if defined(TARGET-I386) && defined(TARGET_ABI32) > > static inline void cpu_set_tls(CPUState *env, target_ulong newtls) > > { > > do_set_thread_area(env, newtls); > > cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector); > > } > > #endif > > do_set_thread_area() is declared static in syscall.c, so you would have > to unstaticize it, create a prototype somewhere (where?), and you would > introduce a dependency between the CPU emulation and the userspace > emulation. These problems are all unique to the i386 architecture which > doesn't get away with just setting a CPU register like all the others. Hm, that's a good point. I imagine the problems are similar on x86-64. My first thought was to simply move do_set_thread_area and cpu_set_tls (the latter for all architectures, not just x86) to linux-user/target-FOO/syscall.h. But that won't work for ARM, since it uses cpu_set_tls in linux-user/main.c. Maybe creating a new file/header for cpu-specific support code would be the right way to do things; you might have to make cpu_set_tls out-of-line, but that's not particularly bad. (This would help with other things, like moving cpu_loop from linux-user/main.c into architecture-specific files.) But that's a little much to tackle for just x86 NPTL support, I suppose. :) -Nathan
diff --git a/configure b/configure index 824b21c..c3c5d4a 100755 --- a/configure +++ b/configure @@ -1894,6 +1894,7 @@ TARGET_ABI_DIR="" case "$target_arch2" in i386) target_phys_bits=32 + target_nptl="yes" ;; x86_64) TARGET_BASE_ARCH=i386 diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5778e32..bbaec3d 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -3730,8 +3730,14 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, ts->child_tidptr = child_tidptr; } - if (nptl_flags & CLONE_SETTLS) + if (nptl_flags & CLONE_SETTLS) { +#if defined(TARGET_I386) && defined(TARGET_ABI32) + do_set_thread_area(new_env, newtls); + cpu_x86_load_seg(new_env, R_GS, new_env->segs[R_GS].selector); +#else cpu_set_tls (new_env, newtls); +#endif + } /* Grab a mutex so that thread setup appears atomic. */ pthread_mutex_lock(&clone_lock); @@ -3804,8 +3810,14 @@ static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, if (flags & CLONE_PARENT_SETTID) put_user_u32(gettid(), parent_tidptr); ts = (TaskState *)env->opaque; - if (flags & CLONE_SETTLS) + if (flags & CLONE_SETTLS) { +#if defined(TARGET_I386) && defined(TARGET_ABI32) + do_set_thread_area(env, newtls); + cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector); +#else cpu_set_tls (env, newtls); +#endif + } if (flags & CLONE_CHILD_CLEARTID) ts->child_tidptr = child_tidptr; #endif
Makes NPTL binaries run by implementing TLS. Signed-off-by: Ulrich Hecht <uli@suse.de> --- configure | 1 + linux-user/syscall.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-)