]>
Commit | Line | Data |
---|---|---|
688903eb | 1 | /* Copyright (C) 2004-2018 Free Software Foundation, Inc. |
8dbe95aa UD |
2 | This file is part of the GNU C Library. |
3 | ||
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Lesser General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Lesser General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
ab84e3ff PE |
15 | License along with the GNU C Library. If not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
8dbe95aa UD |
17 | |
18 | #include <assert.h> | |
19 | #include <stdbool.h> | |
20 | #include <stdlib.h> | |
21 | #include <unistd.h> | |
22 | ||
23 | ||
24 | static long int linux_sysconf (int name); | |
25 | ||
26 | #define CSHAPE(totalsize, linesize, assoc) \ | |
27 | ((totalsize & ~0xff) | (linesize << 4) | assoc) | |
28 | ||
e8f99945 | 29 | extern long __libc_alpha_cache_shape[4]; |
8dbe95aa | 30 | |
8dbe95aa UD |
31 | /* Get the value of the system variable NAME. */ |
32 | long int | |
33 | __sysconf (int name) | |
34 | { | |
35 | long shape, index; | |
36 | ||
37 | /* We only handle the cache information here (for now). */ | |
38 | if (name < _SC_LEVEL1_ICACHE_SIZE || name > _SC_LEVEL4_CACHE_LINESIZE) | |
39 | return linux_sysconf (name); | |
40 | ||
41 | /* No Alpha has L4 caches. */ | |
42 | if (name >= _SC_LEVEL4_CACHE_SIZE) | |
43 | return -1; | |
44 | ||
45 | index = (name - _SC_LEVEL1_ICACHE_SIZE) / 3; | |
46 | shape = __libc_alpha_cache_shape[index]; | |
47 | if (shape == -2) | |
48 | { | |
49 | long shape_l1i, shape_l1d, shape_l2, shape_l3 = -1; | |
50 | ||
51 | /* ??? In the cases below for which we do not know L1 cache sizes, | |
52 | we could do timings to measure sizes. But for the Bcache, it's | |
53 | generally big enough that (without additional help) TLB effects | |
54 | get in the way. We'd either need to be able to allocate large | |
55 | pages or have the kernel do the timings from KSEG. Fortunately, | |
56 | kernels beginning with 2.6.5 will pass us this info in auxvec. */ | |
57 | ||
c0b21b69 | 58 | switch (__builtin_alpha_implver ()) |
8dbe95aa UD |
59 | { |
60 | case 0: /* EV4 */ | |
61 | /* EV4/LCA45 had 8k L1 caches; EV45 had 16k L1 caches. */ | |
62 | /* EV4/EV45 had 128k to 16M 32-byte direct Bcache. LCA45 | |
63 | had 64k to 8M 8-byte direct Bcache. Can't tell. */ | |
64 | shape_l1i = shape_l1d = shape_l2 = CSHAPE (0, 5, 1); | |
65 | break; | |
66 | ||
67 | case 1: /* EV5 */ | |
c0b21b69 | 68 | if (__builtin_alpha_amask (1 << 8)) |
8dbe95aa UD |
69 | { |
70 | /* MAX insns not present; either EV5 or EV56. */ | |
71 | shape_l1i = shape_l1d = CSHAPE(8*1024, 5, 1); | |
72 | /* ??? L2 and L3 *can* be configured as 32-byte line. */ | |
73 | shape_l2 = CSHAPE (96*1024, 6, 3); | |
74 | /* EV5/EV56 has 1M to 16M Bcache. */ | |
75 | shape_l3 = CSHAPE (0, 6, 1); | |
76 | } | |
77 | else | |
78 | { | |
79 | /* MAX insns present; either PCA56 or PCA57. */ | |
80 | /* PCA56 had 16k 64-byte cache; PCA57 had 32k Icache. */ | |
81 | /* PCA56 had 8k 64-byte cache; PCA57 had 16k Dcache. */ | |
82 | /* PCA5[67] had 512k to 4M Bcache. */ | |
83 | shape_l1i = shape_l1d = shape_l2 = CSHAPE (0, 6, 1); | |
84 | } | |
85 | break; | |
86 | ||
87 | case 2: /* EV6 */ | |
88 | shape_l1i = shape_l1d = CSHAPE(64*1024, 6, 2); | |
89 | /* EV6/EV67/EV68* had 1M to 16M Bcache. */ | |
90 | shape_l2 = CSHAPE (0, 6, 1); | |
91 | break; | |
92 | ||
93 | case 3: /* EV7 */ | |
94 | shape_l1i = shape_l1d = CSHAPE(64*1024, 6, 2); | |
95 | shape_l2 = CSHAPE(7*1024*1024/4, 6, 7); | |
96 | break; | |
97 | ||
98 | default: | |
99 | shape_l1i = shape_l1d = shape_l2 = 0; | |
100 | break; | |
101 | } | |
102 | ||
103 | __libc_alpha_cache_shape[0] = shape_l1i; | |
104 | __libc_alpha_cache_shape[1] = shape_l1d; | |
105 | __libc_alpha_cache_shape[2] = shape_l2; | |
106 | __libc_alpha_cache_shape[3] = shape_l3; | |
107 | shape = __libc_alpha_cache_shape[index]; | |
108 | } | |
109 | ||
110 | if (shape <= 0) | |
111 | return shape; | |
112 | ||
3287d416 | 113 | switch ((name - _SC_LEVEL1_ICACHE_SIZE) % 3) |
8dbe95aa UD |
114 | { |
115 | case 0: /* total size */ | |
116 | return shape & -0x100; | |
117 | case 1: /* associativity */ | |
118 | return shape & 0xf; | |
119 | default: /* line size */ | |
120 | return 1L << ((shape >> 4) & 0xf); | |
121 | } | |
122 | } | |
123 | ||
124 | /* Now the generic Linux version. */ | |
125 | #undef __sysconf | |
126 | #define __sysconf static linux_sysconf | |
97d1e7c8 | 127 | #include <sysdeps/unix/sysv/linux/sysconf.c> |