From 8dbe95aa6adffe90b37091550f57ceafa84a6305 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Fri, 7 May 2004 01:57:19 +0000 Subject: [PATCH] Linux/Alpha sysconf definitions. --- sysdeps/unix/sysv/linux/alpha/sysconf.c | 152 ++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 sysdeps/unix/sysv/linux/alpha/sysconf.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 +#include +#include +#include + + +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"