NPTL/TLS support
PATCH 1/1 NPTL/TLS support
The attached patch adds partial support for ARM NPTL binaries.
It implements the following things:
- The Arm magic kernel code page. This is used on recent Arm kernels to provide efficient access to kernel/CPU features. For example atomic operations, and reading the TLS register (which may or may not be a real hardware register). This is simplified version of the VDSO used on recent x86 and ppc kernels.
- A new Arm specific syscall to set the TLS register.
- Support for the 5-argument form of sys_clone.
This is sufficient to run single-threaded NPTL enabled binaries. I've not yet implemented the futex syscalls, so multithreaded applications probaby won't work.
NPTL support is only enabled for ARM. Other architectures may need architecture specific bits implementing before they can be enabled.
Paul
Index: configure
===================================================================
RCS file: /cvsroot/qemu/qemu/configure,v
retrieving revision 1.73
configure +12 -0
@@ -85,6 +85,7 @@ kqemu="no" kernel_path="" cocoa="no" check_gfx="yes" +nptl="yes" # OS specific targetos=`uname -s`
@@ -191,6 +192,8 @@ for opt do ;; --disable-gfx-check) check_gfx="no" ;; + --disabe-nptl) nptl="no" + ;; esac done
@@ -349,6 +352,7 @@ echo " --enable-adlib enable echo " --enable-fmod enable FMOD audio output driver" echo " --fmod-lib path to FMOD library" echo " --fmod-inc path to FMOD includes" +echo " --disable-nptl Disable NPTL user-mode emulation" echo "" echo "NOTE: The object files are build at the place where configure is launched" exit 1
@@ -736,6 +740,14 @@ if test "$target_user_only" = "no"; then echo -n " `aalib-config --cflags`" >> $config_mak ; fi echo "" >> $config_mak + fi +else + if test "$nptl" = "yes" ; then + case "$target_cpu" in + arm | armeb) + echo "#define USE_NPTL 1" >> $config_h + ;; + esac fi fi
Index: exec-all.h
===================================================================
RCS file: /cvsroot/qemu/qemu/exec-all.h,v
retrieving revision 1.34
exec-all.h +1 -157
164 lines not on this page · raw message
Index: spinlock.h
===================================================================
RCS file: spinlock.h
spinlock.h new file +181 -0
181 lines not on this page · raw message
Index: linux-user/arm-semi.c
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/arm-semi.c,v retrieving revision 1.3
arm-semi.c +1 -1
@@ -178,7 +178,7 @@ uint32_t do_arm_semihosting(CPUState *en ts->heap_limit = limit; } - ptr = (uint32_t *)tswap32 (ARG (0 )); + ptr = (uint32_t *)ARG (0 ); ptr[0 ] =tswap32 (ts->heap_base); ptr[1 ] =tswap32 (ts->heap_limit); ptr[2 ] =tswap32 (ts->stack_base);
Index: linux-user/elfload.c
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/elfload.c,v retrieving revision 1.26
elfload.c +24 -26
67 lines not on this page · raw message
Index: linux-user/main.c
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/main.c,v
retrieving revision 1.70
main.c +80 -12
122 lines not on this page · raw message
Index: linux-user/qemu.h
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/qemu.h,v
retrieving revision 1.24
qemu.h +3 -0
@@ -76,6 +76,9 @@ typedef struct TaskState {uint32_t v86mask;#endif int used;/* non zero if used */ +#ifdef USE_NPTL +uint32_t *child_tidptr; +#endif uint8_t stack[0 ]; } __attribute__((aligned(16))) TaskState;
Index: linux-user/syscall.c
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/syscall.c,v retrieving revision 1.62
syscall.c +82 -5
148 lines not on this page · raw message
Index: linux-user/arm/syscall.h
===================================================================
RCS file: /cvsroot/qemu/qemu/linux-user/arm/syscall.h,v retrieving revision 1.6
arm/syscall.h +3 -1
@@ -28,7 +28,9 @@ struct target_pt_regs {#define ARM_SYSCALL_BASE 0x900000#define ARM_THUMB_SYSCALL 0 -#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2) +#define ARM_NR_BASE 0xf0000 +#define ARM_NR_cacheflush (ARM_NR_BASE + 2) +#define ARM_NR_set_tls (ARM_NR_BASE + 5)#define ARM_NR_semihosting 0x123456#define ARM_NR_thumb_semihosting 0xAB
Index: target-arm/cpu.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-arm/cpu.h,v
retrieving revision 1.10
cpu.h +14 -0
@@ -32,6 +32,7 @@#define EXCP_SWI 2/* software interrupt */ #define EXCP_PREFETCH_ABORT 3#define EXCP_DATA_ABORT 4 +#define EXCP_KERNEL_TRAP 5/* Jumped to kernel code page. */ /* We currently assume float and double are IEEE single and double precision respectively.
@@ -55,6 +56,10 @@ typedef struct CPUARMState {/* coprocessor 15 (MMU) status */ uint32_t cp15_6; +#if defined(CONFIG_USER_ONLY ) && defined(USE_NPTL ) +/* TLS register. */ +uint32_t tls; +#endif /* exception/interrupt handling */ jmp_buf jmp_env;
@@ -106,6 +111,15 @@ void cpu_arm_close(CPUARMState *s);struct siginfo ;int cpu_arm_signal_handler (int host_signum,struct siginfo *info,void *puc); + +void cpu_lock (void ); +void cpu_unlock (void ); +#if defined(USE_NPTL ) +static inline void cpu_set_tls (CPUARMState *env,void *newtls) +{ + env->tls = (uint32_t )newtls; +} +#endif #define TARGET_PAGE_BITS 12#include "cpu-all.h"
Index: target-arm/exec.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-arm/exec.h,v
retrieving revision 1.5
exec.h +0 -2
@@ -57,8 +57,6 @@ int cpu_arm_handle_mmu_fault (CPUState */* In op_helper.c */ -void cpu_lock (void ); -void cpu_unlock (void );void cpu_loop_exit (void );void raise_exception (int );
Index: target-arm/op.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-arm/op.c,v
retrieving revision 1.14
op.c +6 -0
@@ -887,6 +887,12 @@ void OPPROTO op_debug(void)cpu_loop_exit (); } +void OPPROTO op_kernel_trap(void) +{ + env->exception_index =EXCP_KERNEL_TRAP ; +cpu_loop_exit (); +} +/* VFP support. We follow the convention used for VFP instrunctions: Single precition routines have a "s" suffix, double precision a "d" suffix. */
Index: target-arm/translate.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-arm/translate.c,v retrieving revision 1.26
translate.c +10 -0
@@ -2034,6 +2034,7 @@ undef: s->is_jmp =DISAS_JUMP ; } +/* generate intermediate code in gen_opc_buf and gen_opparam_buf for basic block 'tb'. If search_pc is TRUE, also generate PC information for each intermediate instruction. */
@@ -2063,6 +2064,15 @@ static inline int gen_intermediate_code_ nb_gen_labels =0 ; lj =-1 ; do { +#ifdef CONFIG_USER_ONLY + /* Intercept jump to the magic kernel page. */ + if (dc->pc > 0xffff0000) { + gen_op_kernel_trap(); + dc->is_jmp = DISAS_UPDATE; + break; + } +#endif + if (env->nb_breakpoints > 0) { for(j = 0; j < env->nb_breakpoints; j++) { if (env->breakpoints[j] == dc->pc) {
Quoted 4 lines · Paul Brook
The attached patch adds partial support for ARM NPTL binaries.
It implements the following things:
Quoted 8 lines
- The Arm magic kernel code page. This is used on recent Arm kernels to
provide efficient access to kernel/CPU features. For example atomic operations, and reading the TLS register (which may or may not be a real hardware register). This is simplified version of the VDSO used on recent x86 and ppc kernels.
- A new Arm specific syscall to set the TLS register.
- Support for the 5-argument form ofsys_clone.This is sufficient to run single-threaded NPTL enabled binaries. I've not yet implemented the futex syscalls, so multithreaded applications probaby won't work.
NPTL support is only enabled for ARM. Other architectures may need architecture specific bits implementing before they can be enabled.
On i386 there are AUXENTs to define the address of the VDSO page (AT_SYSINFO and AT_SYSINFO_EHDR). If it was supported by the ARM glibc, it would avoid some hacks you need to do to intercept calls to it. Can you check that ?
Fabrice.
Quoted 10 lines
Quoted 5 lines
- The Arm magic kernel code page. This is used on recent Arm kernels to provide efficient access to kernel/CPU features. For example atomic operations, and reading the TLS register (which may or may not be a real hardware register). This is simplified version of the VDSO used on recent x86 and ppc kernels.
On i386 there are AUXENTs to define the address of the VDSO page (
AT_SYSINFOandAT_SYSINFO_EHDR). If it was supported by the ARM glibc, it would avoid some hacks you need to do to intercept calls to it. Can you check that ?
Arm does not [yet] use a full VDSO.
As Arm is primarily aimed at embedded targets it was decided that the overhead of a VDSO was undesirable.
In particular a fixed page mapping means an application can use shifter tricks to generate the address and avoid the PLT indirection.
e.g.:__aeabi_read_tp:
mov r0, #0xffff0fff
sub pc, r0, #31Paul
Quoted 3 lines · Paul Brook
This is sufficient to run single-threaded NPTL enabled binaries. I've not yet implemented the futex syscalls, so multithreaded applications probaby won't work.
I followed another approach for our packages: don't use NPTL libraries.
<http://cvs.mandriva.com/cgi-bin/cvsweb.cgi/contrib-SPECS/qemu/qemu-0.7.2-no-nptl.patch>
(but since glibc 2.4 officially drops support for linuxthreads...)
Someone will probably want to revive QEMU user-mode support and merge NPTL/TLS support from IA-32 EL. If not with QEMU, probably use VEX JIT.