1 | /* Copyright (C) 2004-2022 Free Software Foundation, Inc. |
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 |
15 | License along with the GNU C Library. If not, see |
16 | <https://www.gnu.org/licenses/>. */ |
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 | |
29 | extern long __libc_alpha_cache_shape[4]; |
30 | |
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 | |
58 | switch (__builtin_alpha_implver ()) |
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 */ |
68 | if (__builtin_alpha_amask (1 << 8)) |
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 | |
113 | switch ((name - _SC_LEVEL1_ICACHE_SIZE) % 3) |
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 |
127 | #include <sysdeps/unix/sysv/linux/sysconf.c> |
128 | |