i386-linux-user NPTL support
PATCH 1/1 i386-linux-user NPTL support
Makes NPTL binaries run by implementing TLS.
--- configure | 1 + linux-user/syscall.c | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-)
configure +1 -0
@@ -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
linux-user/syscall.c +14 -2
@@ -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
Signature · 1 line
1.6.4
linux-user/syscall.c static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp, · line 3740
Quoted 10 lines · Ulrich Hecht
linux-user/syscall.c +7
-1-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
Quoted 4 lines · Nathan Froyd
Why not just stick things in
cpu_set_tlsintarget-i386/cpu.hlike so:#if defined(TARGET-I386) &&
defined(TARGET_ABI32)static inline voidcpu_set_tls(CPUState *env, target_ulong newtls)
Quoted 8 lines
{ 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
Signature · 1 line
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
Quoted 11 lines · Ulrich Hecht
Quoted 9 lines · Nathan Froyd
Why not just stick things in
cpu_set_tlsintarget-i386/cpu.hlike so:#if defined(TARGET-I386) &&
defined(TARGET_ABI32)static inline voidcpu_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
Quoted 5 lines
do_set_thread_area()is declared static insyscall.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