This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

new syscall stub for ia64 linux


Below is a draft patch to add support to libc for the new syscall stub
I'd like to start using on ia64 linux.  The main change here is that
the syscall stub will do an indirect call via a "sysinfo" pointer
picked up from the thread-control-block.  By default, "sysinfo" points
to a _dl_sysinfo_break(), which does an old-style "break 0x100000"
syscall.  With newer kernels, this will get redefined via AT_SYSINFO
to an entry-point in the kernel's gate page, which does a light-weight
entry into the kernel.

Since it is extremely unpleasant to have to syscall stubs change, I'd
like the tp-offset of the "sysinfo" pointer to be set in stone.  The
ia64 ABI reserves the positive offsets off the thread-pointer for its
own purposes, so I'd like to propose an offset of -8.  In the patch
below, I did this by moving the "p_header" in _pthread_desc_struct to
the end of the structure (if TLS_TCB_AT_TP is not defined).

Most of the other changes should be pretty obvious.  One rather ugly
hack though is that in libc-start.c, I had to reverse the order of
DL_SYSDEP_OSCHEC() and __pthread_initialize_minimal(): the former
calls uname() and with the new syscall stub, the thread-pointer needs
to be valid before a system call can be invoked.  If this isn't
acceptable, suggestions for improvements would be welcome.

Thanks,

	--david

PS: No ChangeLog since I just want to get feedback at this point---the
    patch isn't ready for prime-time yet.

PPS: Relative to what was discussed on the linux-ia64 mailing list,
    I changed the syscall stub slightly: r9 got replaced by r11, because
    some system calls (e.g., pipe()) use r9 to return a second return
    value.  r11 should be safe that way.

Index: linuxthreads/descr.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/descr.h,v
retrieving revision 1.8
diff -u -r1.8 descr.h
--- linuxthreads/descr.h	28 Dec 2002 10:14:16 -0000	1.8
+++ linuxthreads/descr.h	14 Jan 2003 07:09:56 -0000
@@ -109,6 +109,7 @@
 
 struct _pthread_descr_struct {
   /* XXX Remove this union for IA-64 style TLS module */
+#if TLS_TCB_AT_TP
   union {
     struct {
       void *tcb;		/* Pointer to the TCB.  This is not always
@@ -122,6 +123,9 @@
     } data;
     void *__padding[16];
   } p_header;
+#else
+  /* New elements must be added at the beginning.  */
+#endif
   pthread_descr p_nextlive, p_prevlive;
                                 /* Double chaining of active threads */
   pthread_descr p_nextwaiting;  /* Next element in the queue holding the thr */
@@ -180,7 +184,23 @@
 #endif
   size_t p_alloca_cutoff;	/* Maximum size which should be allocated
 				   using alloca() instead of malloc().  */
+#if TLS_TCB_AT_TP
   /* New elements must be added at the end.  */
+#else
+  union {
+    struct {
+      void *reserved[11];	/* reserve for future use */
+      void *tcb;		/* XXX do we really need this? */
+      union dtv *dtvp;		/* XXX do we really need this? */
+      pthread_descr self;	/* XXX do we really need this? */
+      int multiple_threads;
+#ifdef NEED_DL_SYSINFO
+      uintptr_t sysinfo;
+#endif
+    } data;
+    void *__padding[16];
+  } p_header __attribute__ ((aligned(32)));
+#endif
 } __attribute__ ((aligned(32))); /* We need to align the structure so that
 				    doubles are aligned properly.  This is 8
 				    bytes on MIPS and 16 bytes on MIPS64.
Index: linuxthreads/sysdeps/ia64/tcb-offsets.sym
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/ia64/tcb-offsets.sym,v
retrieving revision 1.2
diff -u -r1.2 tcb-offsets.sym
--- linuxthreads/sysdeps/ia64/tcb-offsets.sym	12 Jan 2003 08:39:41 -0000	1.2
+++ linuxthreads/sysdeps/ia64/tcb-offsets.sym	14 Jan 2003 07:09:56 -0000
@@ -2,3 +2,9 @@
 #include <tls.h>
 
 MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_header.data.multiple_threads) - sizeof (struct _pthread_descr_struct)
+
+#ifdef HAVE_TLS_SUPPORT
+
+SYSINFO_OFFSET		offsetof (struct _pthread_descr_struct, p_header.data.sysinfo) - sizeof (struct _pthread_descr_struct)
+
+#endif
Index: linuxthreads/sysdeps/ia64/tls.h
===================================================================
RCS file: /cvs/glibc/libc/linuxthreads/sysdeps/ia64/tls.h,v
retrieving revision 1.3
diff -u -r1.3 tls.h
--- linuxthreads/sysdeps/ia64/tls.h	12 Jan 2003 08:38:42 -0000	1.3
+++ linuxthreads/sysdeps/ia64/tls.h	14 Jan 2003 07:09:56 -0000
@@ -20,10 +20,13 @@
 #ifndef _TLS_H
 #define _TLS_H
 
+#include <dl-sysdep.h>
+
 #ifndef __ASSEMBLER__
 
 # include <pt-machine.h>
 # include <stddef.h>
+# include <stdint.h>
 
 /* Type for the dtv.  */
 typedef union dtv
@@ -83,8 +86,10 @@
 /* Code to initially initialize the thread pointer.  This might need
    special attention since 'errno' is not yet available and if the
    operation can cause a failure 'errno' must not be touched.  */
-#  define TLS_INIT_TP(tcbp, secondcall) \
-  (__thread_self = (tcbp), NULL)
+#  define TLS_INIT_TP(tcbp, secondcall)			\
+  (__thread_self = (tcbp),				\
+   THREAD_SELF->p_header.data.sysinfo = GL(dl_sysinfo),	\
+   NULL)
 
 /* Return the address of the dtv for the current thread.  */
 #  define THREAD_DTV() \
@@ -114,6 +119,7 @@
     static struct _pthread_descr_struct nontls_init_tp			\
       = { .p_header.data.multiple_threads = 0 };			\
     __thread_self = ((__typeof (__thread_self)) &nontls_init_tp) + 1;	\
+    THREAD_SELF->p_header.data.sysinfo = GL(dl_sysinfo);		\
   } while (0)
 
 #endif
Index: linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
===================================================================
RCS file: linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
diff -N linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linuxthreads/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h	14 Jan 2003 07:09:56 -0000
@@ -0,0 +1,43 @@
+/* System-specific settings for dynamic linker code.  IA-64 version.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _DL_SYSDEP_H
+#define _DL_SYSDEP_H	1
+
+#define NEED_DL_SYSINFO
+
+#ifndef __ASSEMBLER__
+/* Don't declare this as a function---we want it's entry-point, not
+   it's function descriptor... */
+extern int _dl_sysinfo_break attribute_hidden;
+# define DL_SYSINFO_DEFAULT ((uintptr_t) &_dl_sysinfo_break)
+# define DL_SYSINFO_IMPLEMENTATION			\
+  asm (".text\n\t"					\
+       ".hidden _dl_sysinfo_break\n\t"			\
+       ".proc _dl_sysinfo_break\n\t"			\
+       "_dl_sysinfo_break:\n\t"				\
+       ".prologue\n\t"					\
+       ".altrp b6\n\t"					\
+       ".body\n\t"					\
+       "break 0x100000;\n\t"				\
+       "br.ret.sptk.many b6;\n\t"			\
+       ".endp _dl_sysinfo_break");
+#endif
+
+#endif	/* dl-sysdep.h */
Index: sysdeps/generic/libc-start.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/generic/libc-start.c,v
retrieving revision 1.35
diff -u -r1.35 libc-start.c
--- sysdeps/generic/libc-start.c	28 Dec 2002 09:14:52 -0000	1.35
+++ sysdeps/generic/libc-start.c	14 Jan 2003 07:09:56 -0000
@@ -83,14 +83,6 @@
   ++auxvec;
   _dl_aux_init ((ElfW(auxv_t) *) auxvec);
 # endif
-# ifdef DL_SYSDEP_OSCHECK
-  if (!__libc_multiple_libcs)
-    {
-      /* This needs to run to initiliaze _dl_osversion before TLS
-	 setup might check it.  */
-      DL_SYSDEP_OSCHECK (__libc_fatal);
-    }
-# endif
 
   /* Initialize the thread library at least a bit since the libgcc
      functions are using thread functions if these are available and
@@ -101,6 +93,15 @@
   if (__pthread_initialize_minimal)
 # endif
     __pthread_initialize_minimal ();
+
+# ifdef DL_SYSDEP_OSCHECK
+  if (!__libc_multiple_libcs)
+    {
+      /* This needs to run to initiliaze _dl_osversion before TLS
+	 setup might check it.  */
+      DL_SYSDEP_OSCHECK (__libc_fatal);
+    }
+# endif
 
   /* Some security at this point.  Prevent starting a SUID binary where
      the standard file descriptors are not opened.  We have to do this
Index: sysdeps/unix/sysv/linux/ia64/sysdep.h
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/ia64/sysdep.h,v
retrieving revision 1.10
diff -u -r1.10 sysdep.h
--- sysdeps/unix/sysv/linux/ia64/sysdep.h	9 Jan 2003 04:09:25 -0000	1.10
+++ sysdeps/unix/sysv/linux/ia64/sysdep.h	14 Jan 2003 07:09:57 -0000
@@ -23,6 +23,7 @@
 
 #include <sysdeps/unix/sysdep.h>
 #include <sysdeps/ia64/sysdep.h>
+#include <tls.h>
 
 /* For Linux we can use the system call table in the header file
 	/usr/include/asm/unistd.h
@@ -89,9 +90,30 @@
 	cmp.eq p6,p0=-1,r10;			\
 (p6)	br.cond.spnt.few __syscall_error;
 
+#if defined HAVE_TLS_SUPPORT && (!defined NOT_IN_libc || defined IS_IN_libpthread)
+
+/* Use the lightweight stub only if (a) we have a suitably modern
+   thread-control block (HAVE_TLS_SUPPORT) and (b) we're not compiling
+   the runtime loader (which might do syscalls before being fully
+   relocated). */
+
+#define DO_CALL(num)				\
+	.prologue;				\
+        adds r2 = SYSINFO_OFFSET, r13;;		\
+        ld8 r2 = [r2];				\
+	.save ar.pfs, r11;			\
+        mov r11 = ar.pfs;;			\
+	.body;					\
+	mov r15 = num;				\
+        mov b7 = r2;				\
+        br.call.sptk.many b6 = b7;;		\
+	.restore sp;				\
+        mov ar.pfs = r11
+#else
 #define DO_CALL(num)				\
 	mov r15=num;				\
 	break __BREAK_SYSCALL;
+#endif
 
 #undef PSEUDO_END
 #define PSEUDO_END(name)	.endp C_SYMBOL_NAME(name);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]