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


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

alpha cache detection


Kernels 2.6.4+ add a couple of AT values for cache parameters
that we cannot determine from userspace.

Is there a better way to read the AT values from libc startup
instead of ld.so startup such that we don't have to export
symbols like this?


r~



	* elf/elf.h (AT_L1I_CACHESHAPE, AT_L1D_CACHESHAPE,
	AT_L2_CACHESHAPE, AT_L3_CACHESHAPE): New.
	* sysdeps/unix/sysv/linux/alpha/Versions: Export
	__libc_alpha_cache_shape as a private symbol.
	* sysdeps/unix/sysv/linux/alpha/dl-sysdep.c: New file.
	* sysdeps/unix/sysv/linux/alpha/sysconf.c: New file.

Index: elf/elf.h
===================================================================
RCS file: /cvs/glibc/libc/elf/elf.h,v
retrieving revision 1.139
diff -c -p -d -r1.139 elf.h
*** elf/elf.h	1 Apr 2004 18:48:40 -0000	1.139
--- elf/elf.h	6 May 2004 22:04:46 -0000
*************** typedef struct
*** 963,968 ****
--- 963,974 ----
  #define AT_SYSINFO	32
  #define AT_SYSINFO_EHDR	33
  
+ /* Shapes of the caches.  Bits 0-3 contains associativity; bits 4-7 contains
+    log2 of line size; mask those to get cache size.  */
+ #define AT_L1I_CACHESHAPE	34
+ #define AT_L1D_CACHESHAPE	35
+ #define AT_L2_CACHESHAPE	36
+ #define AT_L3_CACHESHAPE	37
  
  /* Note section contents.  Each entry in the note section begins with
     a header of a fixed form.  */
Index: sysdeps/unix/sysv/linux/alpha/Versions
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/unix/sysv/linux/alpha/Versions,v
retrieving revision 1.11
diff -c -p -d -r1.11 Versions
*** sysdeps/unix/sysv/linux/alpha/Versions	28 Aug 2002 23:55:01 -0000	1.11
--- sysdeps/unix/sysv/linux/alpha/Versions	6 May 2004 22:04:51 -0000
*************** libc {
*** 73,78 ****
--- 73,86 ----
      #errlist-compat	132
      _sys_errlist; sys_errlist; _sys_nerr; sys_nerr;
    }
+   GLIBC_PRIVATE {
+     __libc_alpha_cache_shape;
+   }
+ }
+ ld {
+   GLIBC_PRIVATE {
+     __libc_alpha_cache_shape;
+   }
  }
  librt {
    GLIBC_2.3 {
Index: sysdeps/unix/sysv/linux/alpha/dl-sysdep.c
===================================================================
RCS file: sysdeps/unix/sysv/linux/alpha/dl-sysdep.c
diff -N sysdeps/unix/sysv/linux/alpha/dl-sysdep.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sysdeps/unix/sysv/linux/alpha/dl-sysdep.c	6 May 2004 22:04:51 -0000
***************
*** 0 ****
--- 1,60 ----
+ /* Operating system support for run-time dynamic linker.  Linux/PPC version.
+    Copyright (C) 1997, 1998, 2001, 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.  */
+ 
+ 
+ #include "config.h"
+ #include "kernel-features.h"
+ #include <ldsodefs.h>
+ 
+ extern long __libc_alpha_cache_shape[4];
+ weak_extern (__libc_alpha_cache_shape);
+ 
+ 
+ /* Scan the Aux Vector for the cache shape entries.  */
+ #define DL_PLATFORM_AUXV				\
+       case AT_L1I_CACHESHAPE:				\
+ 	{						\
+ 	  long *cls = __libc_alpha_cache_shape;		\
+ 	  if (cls != NULL)				\
+ 	    cls[0] = av->a_un.a_val;			\
+ 	  break;					\
+ 	}						\
+       case AT_L1D_CACHESHAPE:				\
+ 	{						\
+ 	  long *cls = __libc_alpha_cache_shape;		\
+ 	  if (cls != NULL)				\
+ 	    cls[1] = av->a_un.a_val;			\
+ 	  break;					\
+ 	}						\
+       case AT_L2_CACHESHAPE:				\
+ 	{						\
+ 	  long *cls = __libc_alpha_cache_shape;		\
+ 	  if (cls != NULL)				\
+ 	    cls[2] = av->a_un.a_val;			\
+ 	  break;					\
+ 	}						\
+       case AT_L3_CACHESHAPE:				\
+ 	{						\
+ 	  long *cls = __libc_alpha_cache_shape;		\
+ 	  if (cls != NULL)				\
+ 	    cls[3] = av->a_un.a_val;			\
+ 	  break;					\
+ 	}
+ 
+ #include <sysdeps/unix/sysv/linux/dl-sysdep.c>
Index: sysdeps/unix/sysv/linux/alpha/sysconf.c
===================================================================
RCS file: sysdeps/unix/sysv/linux/alpha/sysconf.c
diff -N sysdeps/unix/sysv/linux/alpha/sysconf.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- sysdeps/unix/sysv/linux/alpha/sysconf.c	6 May 2004 22:04:51 -0000
***************
*** 0 ****
--- 1,152 ----
+ /* Copyright (C) 2004 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.  */
+ 
+ #include <assert.h>
+ #include <stdbool.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ 
+ 
+ static long int linux_sysconf (int name);
+ 
+ #define CSHAPE(totalsize, linesize, assoc) \
+   ((totalsize & ~0xff) | (linesize << 4) | assoc)
+ 
+ long __libc_alpha_cache_shape[4] = { -2, -2, -2, -2 };
+ 
+ static inline unsigned long
+ implver (void)
+ {
+   unsigned long i;
+ #if __GNUC_PREREQ(3,3)
+   i = __builtin_alpha_implver ();
+ #else
+   asm ("implver %0" : "=r" (i));
+ #endif
+   return i;
+ }
+ 
+ static inline unsigned long
+ amask (unsigned long x)
+ {
+   unsigned long r;
+ #if __GNUC_PREREQ(3,3)
+   r = __builtin_alpha_amask (x);
+ #else
+   asm ("amask %1,%0" : "=r"(r) : "Ir"(x));
+ #endif
+   return r;
+ }
+ 
+ /* Get the value of the system variable NAME.  */
+ long int
+ __sysconf (int name)
+ {
+   long shape, index;
+ 
+   /* We only handle the cache information here (for now).  */
+   if (name < _SC_LEVEL1_ICACHE_SIZE || name > _SC_LEVEL4_CACHE_LINESIZE)
+     return linux_sysconf (name);
+ 
+   /* No Alpha has L4 caches.  */
+   if (name >= _SC_LEVEL4_CACHE_SIZE)
+     return -1;
+ 
+   index = (name - _SC_LEVEL1_ICACHE_SIZE) / 3;
+   shape = __libc_alpha_cache_shape[index];
+   if (shape == -2)
+     {
+       long shape_l1i, shape_l1d, shape_l2, shape_l3 = -1;
+ 
+       /* ??? In the cases below for which we do not know L1 cache sizes,
+ 	 we could do timings to measure sizes.  But for the Bcache, it's
+ 	 generally big enough that (without additional help) TLB effects
+ 	 get in the way.  We'd either need to be able to allocate large
+ 	 pages or have the kernel do the timings from KSEG.  Fortunately,
+ 	 kernels beginning with 2.6.5 will pass us this info in auxvec.  */
+ 
+       switch (implver())
+ 	{
+ 	case 0: /* EV4 */
+ 	  /* EV4/LCA45 had 8k L1 caches; EV45 had 16k L1 caches.  */
+ 	  /* EV4/EV45 had 128k to 16M 32-byte direct Bcache.  LCA45
+ 	     had 64k to 8M 8-byte direct Bcache.  Can't tell.  */
+ 	  shape_l1i = shape_l1d = shape_l2 = CSHAPE (0, 5, 1);
+ 	  break;
+ 
+ 	case 1: /* EV5 */
+ 	  if (amask (1 << 8))
+ 	    {
+ 	      /* MAX insns not present; either EV5 or EV56.  */
+ 	      shape_l1i = shape_l1d = CSHAPE(8*1024, 5, 1);
+ 	      /* ??? L2 and L3 *can* be configured as 32-byte line.  */
+ 	      shape_l2 = CSHAPE (96*1024, 6, 3);
+ 	      /* EV5/EV56 has 1M to 16M Bcache.  */
+ 	      shape_l3 = CSHAPE (0, 6, 1);
+ 	    }
+ 	  else
+ 	    {
+ 	      /* MAX insns present; either PCA56 or PCA57.  */
+ 	      /* PCA56 had 16k 64-byte cache; PCA57 had 32k Icache.  */
+ 	      /* PCA56 had 8k 64-byte cache; PCA57 had 16k Dcache.  */
+ 	      /* PCA5[67] had 512k to 4M Bcache.  */
+ 	      shape_l1i = shape_l1d = shape_l2 = CSHAPE (0, 6, 1);
+ 	    }
+ 	  break;
+ 
+ 	case 2: /* EV6 */
+ 	  shape_l1i = shape_l1d = CSHAPE(64*1024, 6, 2);
+ 	  /* EV6/EV67/EV68* had 1M to 16M Bcache.  */
+ 	  shape_l2 = CSHAPE (0, 6, 1);
+ 	  break;
+ 
+ 	case 3: /* EV7 */
+ 	  shape_l1i = shape_l1d = CSHAPE(64*1024, 6, 2);
+ 	  shape_l2 = CSHAPE(7*1024*1024/4, 6, 7);
+ 	  break;
+ 
+ 	default:
+ 	  shape_l1i = shape_l1d = shape_l2 = 0;
+ 	  break;
+ 	}
+ 
+       __libc_alpha_cache_shape[0] = shape_l1i;
+       __libc_alpha_cache_shape[1] = shape_l1d;
+       __libc_alpha_cache_shape[2] = shape_l2;
+       __libc_alpha_cache_shape[3] = shape_l3;
+       shape = __libc_alpha_cache_shape[index];
+     }
+ 
+   if (shape <= 0)
+     return shape;
+ 
+   switch (name % 3)
+     {
+     case 0: /* total size */
+       return shape & -0x100;
+     case 1: /* associativity */
+       return shape & 0xf;
+     default: /* line size */
+       return 1L << ((shape >> 4) & 0xf);
+     }
+ }
+ 
+ /* Now the generic Linux version.  */
+ #undef __sysconf
+ #define __sysconf static linux_sysconf
+ #include "../sysconf.c"


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