Skip to contentSkip to conversation

NPTL/TLS support

PATCH In review Paul Brook 3 participants 4 messages Aug 14, 2005 – Nov 14, 2005

lore
Share & tools
lore

Paul Brook

author
#0 lore raw

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
diff -u -p -r1.73 configure
@@ -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
diff -u -p -r1.3 arm-semi.c
@@ -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
diff -u -p -r1.24 qemu.h
@@ -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
diff -u -p -r1.6 syscall.h
@@ -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
diff -u -p -r1.10 cpu.h
@@ -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
diff -u -p -r1.5 exec.h
@@ -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
diff -u -p -r1.14 op.c
@@ -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
diff -u -p -r1.26 translate.c
@@ -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) {
#1 lore raw
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 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.

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.

author
#2 lore raw
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_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 ?

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, #31

Paul

#3 lore raw
In reply to Paul Brook
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.