diff options
Diffstat (limited to 'sysdeps/unix/sysv')
-rw-r--r-- | sysdeps/unix/sysv/linux/alpha/Versions | 8 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/alpha/dl-sysdep.c | 60 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/alpha/sysconf.c | 152 |
3 files changed, 220 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/alpha/Versions b/sysdeps/unix/sysv/linux/alpha/Versions index 89ec9db1c4..ca79c7e444 100644 --- a/sysdeps/unix/sysv/linux/alpha/Versions +++ b/sysdeps/unix/sysv/linux/alpha/Versions @@ -73,6 +73,14 @@ libc { #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 { diff --git a/sysdeps/unix/sysv/linux/alpha/dl-sysdep.c b/sysdeps/unix/sysv/linux/alpha/dl-sysdep.c new file mode 100644 index 0000000000..a0214b0072 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/dl-sysdep.c @@ -0,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> diff --git a/sysdeps/unix/sysv/linux/alpha/sysconf.c b/sysdeps/unix/sysv/linux/alpha/sysconf.c new file mode 100644 index 0000000000..2bbaf1f364 --- /dev/null +++ b/sysdeps/unix/sysv/linux/alpha/sysconf.c @@ -0,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" |