2 Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 static const struct intel_02_cache_info
35 { 0x06, _SC_LEVEL1_ICACHE_SIZE
, 8192, 4, 32 },
36 { 0x08, _SC_LEVEL1_ICACHE_SIZE
, 16384, 4, 32 },
37 { 0x0a, _SC_LEVEL1_DCACHE_SIZE
, 8192, 2, 32 },
38 { 0x0c, _SC_LEVEL1_DCACHE_SIZE
, 16384, 4, 32 },
39 { 0x22, _SC_LEVEL3_CACHE_SIZE
, 524288, 4, 64 },
40 { 0x23, _SC_LEVEL3_CACHE_SIZE
, 1048576, 8, 64 },
41 { 0x25, _SC_LEVEL3_CACHE_SIZE
, 2097152, 8, 64 },
42 { 0x29, _SC_LEVEL3_CACHE_SIZE
, 4194304, 8, 64 },
43 { 0x2c, _SC_LEVEL1_DCACHE_SIZE
, 32768, 8, 64 },
44 { 0x30, _SC_LEVEL1_ICACHE_SIZE
, 32768, 8, 64 },
45 { 0x39, _SC_LEVEL2_CACHE_SIZE
, 131072, 4, 64 },
46 { 0x3a, _SC_LEVEL2_CACHE_SIZE
, 196608, 6, 64 },
47 { 0x3b, _SC_LEVEL2_CACHE_SIZE
, 131072, 2, 64 },
48 { 0x3c, _SC_LEVEL2_CACHE_SIZE
, 262144, 4, 64 },
49 { 0x3d, _SC_LEVEL2_CACHE_SIZE
, 393216, 6, 64 },
50 { 0x3e, _SC_LEVEL2_CACHE_SIZE
, 524288, 4, 64 },
51 { 0x41, _SC_LEVEL2_CACHE_SIZE
, 131072, 4, 32 },
52 { 0x42, _SC_LEVEL2_CACHE_SIZE
, 262144, 4, 32 },
53 { 0x43, _SC_LEVEL2_CACHE_SIZE
, 524288, 4, 32 },
54 { 0x44, _SC_LEVEL2_CACHE_SIZE
, 1048576, 4, 32 },
55 { 0x45, _SC_LEVEL2_CACHE_SIZE
, 2097152, 4, 32 },
56 { 0x46, _SC_LEVEL3_CACHE_SIZE
, 4194304, 4, 64 },
57 { 0x47, _SC_LEVEL3_CACHE_SIZE
, 8388608, 8, 64 },
58 { 0x48, _SC_LEVEL2_CACHE_SIZE
, 3145728, 12, 64 },
59 { 0x49, _SC_LEVEL2_CACHE_SIZE
, 4194304, 16, 64 },
60 { 0x4a, _SC_LEVEL3_CACHE_SIZE
, 6291456, 12, 64 },
61 { 0x4b, _SC_LEVEL3_CACHE_SIZE
, 8388608, 16, 64 },
62 { 0x4c, _SC_LEVEL3_CACHE_SIZE
, 12582912, 12, 64 },
63 { 0x4d, _SC_LEVEL3_CACHE_SIZE
, 16777216, 16, 64 },
64 { 0x4e, _SC_LEVEL2_CACHE_SIZE
, 6291456, 24, 64 },
65 { 0x60, _SC_LEVEL1_DCACHE_SIZE
, 16384, 8, 64 },
66 { 0x66, _SC_LEVEL1_DCACHE_SIZE
, 8192, 4, 64 },
67 { 0x67, _SC_LEVEL1_DCACHE_SIZE
, 16384, 4, 64 },
68 { 0x68, _SC_LEVEL1_DCACHE_SIZE
, 32768, 4, 64 },
69 { 0x78, _SC_LEVEL2_CACHE_SIZE
, 1048576, 8, 64 },
70 { 0x79, _SC_LEVEL2_CACHE_SIZE
, 131072, 8, 64 },
71 { 0x7a, _SC_LEVEL2_CACHE_SIZE
, 262144, 8, 64 },
72 { 0x7b, _SC_LEVEL2_CACHE_SIZE
, 524288, 8, 64 },
73 { 0x7c, _SC_LEVEL2_CACHE_SIZE
, 1048576, 8, 64 },
74 { 0x7d, _SC_LEVEL2_CACHE_SIZE
, 2097152, 8, 64 },
75 { 0x7f, _SC_LEVEL2_CACHE_SIZE
, 524288, 2, 64 },
76 { 0x82, _SC_LEVEL2_CACHE_SIZE
, 262144, 8, 32 },
77 { 0x83, _SC_LEVEL2_CACHE_SIZE
, 524288, 8, 32 },
78 { 0x84, _SC_LEVEL2_CACHE_SIZE
, 1048576, 8, 32 },
79 { 0x85, _SC_LEVEL2_CACHE_SIZE
, 2097152, 8, 32 },
80 { 0x86, _SC_LEVEL2_CACHE_SIZE
, 524288, 4, 64 },
81 { 0x87, _SC_LEVEL2_CACHE_SIZE
, 1048576, 8, 64 },
84 #define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known [0]))
87 intel_02_known_compare (const void *p1
, const void *p2
)
89 const struct intel_02_cache_info
*i1
;
90 const struct intel_02_cache_info
*i2
;
92 i1
= (const struct intel_02_cache_info
*) p1
;
93 i2
= (const struct intel_02_cache_info
*) p2
;
95 if (i1
->idx
== i2
->idx
)
98 return i1
->idx
< i2
->idx
? -1 : 1;
103 __attribute__ ((noinline
))
104 intel_check_word (int name
, unsigned int value
, bool *has_level_2
,
105 bool *no_level_2_or_3
)
107 if ((value
& 0x80000000) != 0)
108 /* The register value is reserved. */
111 /* Fold the name. The _SC_ constants are always in the order SIZE,
113 int folded_name
= (_SC_LEVEL1_ICACHE_SIZE
114 + ((name
- _SC_LEVEL1_ICACHE_SIZE
) / 3) * 3);
118 unsigned int byte
= value
& 0xff;
122 *no_level_2_or_3
= true;
124 if (folded_name
== _SC_LEVEL3_CACHE_SIZE
)
125 /* No need to look further. */
130 if (byte
== 0x49 && folded_name
== _SC_LEVEL3_CACHE_SIZE
)
132 /* Intel reused this value. For family 15, model 6 it
133 specifies the 3rd level cache. Otherwise the 2nd
139 asm volatile ("cpuid"
140 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
143 unsigned int family
= ((eax
>> 20) & 0xff) + ((eax
>> 8) & 0xf);
144 unsigned int model
= ((((eax
>>16) & 0xf) << 4)
145 + ((eax
>> 4) & 0xf));
146 if (family
== 15 && model
== 6)
148 /* The level 3 cache is encoded for this model like
149 the level 2 cache is for other models. Pretend
150 the caller asked for the level 2 cache. */
151 name
= (_SC_LEVEL2_CACHE_SIZE
152 + (name
- _SC_LEVEL3_CACHE_SIZE
));
153 folded_name
= _SC_LEVEL3_CACHE_SIZE
;
157 struct intel_02_cache_info
*found
;
158 struct intel_02_cache_info search
;
161 found
= bsearch (&search
, intel_02_known
, nintel_02_known
,
162 sizeof (intel_02_known
[0]), intel_02_known_compare
);
165 if (found
->name
== folded_name
)
167 unsigned int offset
= name
- folded_name
;
175 assert (offset
== 2);
176 return found
->linesize
;
179 if (found
->name
== _SC_LEVEL2_CACHE_SIZE
)
184 /* Next byte for the next round. */
193 static long int __attribute__ ((noinline
))
194 handle_intel (int name
, unsigned int maxidx
)
196 assert (maxidx
>= 2);
198 /* OK, we can use the CPUID instruction to get all info about the
200 unsigned int cnt
= 0;
201 unsigned int max
= 1;
203 bool no_level_2_or_3
= false;
204 bool has_level_2
= false;
212 asm volatile ("cpuid"
213 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
216 /* The low byte of EAX in the first round contain the number of
217 rounds we have to make. At least one, the one we are already
225 /* Process the individual registers' value. */
226 result
= intel_check_word (name
, eax
, &has_level_2
, &no_level_2_or_3
);
230 result
= intel_check_word (name
, ebx
, &has_level_2
, &no_level_2_or_3
);
234 result
= intel_check_word (name
, ecx
, &has_level_2
, &no_level_2_or_3
);
238 result
= intel_check_word (name
, edx
, &has_level_2
, &no_level_2_or_3
);
243 if (name
>= _SC_LEVEL2_CACHE_SIZE
&& name
<= _SC_LEVEL3_CACHE_LINESIZE
251 static long int __attribute__ ((noinline
))
252 handle_amd (int name
)
258 asm volatile ("cpuid"
259 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
262 /* No level 4 cache (yet). */
263 if (name
> _SC_LEVEL3_CACHE_LINESIZE
)
266 unsigned int fn
= 0x80000005 + (name
>= _SC_LEVEL2_CACHE_SIZE
);
270 asm volatile ("cpuid"
271 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
274 if (name
< _SC_LEVEL1_DCACHE_SIZE
)
276 name
+= _SC_LEVEL1_DCACHE_SIZE
- _SC_LEVEL1_ICACHE_SIZE
;
282 case _SC_LEVEL1_DCACHE_SIZE
:
283 return (ecx
>> 14) & 0x3fc00;
285 case _SC_LEVEL1_DCACHE_ASSOC
:
287 if ((ecx
& 0xff) == 0xff)
288 /* Fully associative. */
289 return (ecx
<< 2) & 0x3fc00;
292 case _SC_LEVEL1_DCACHE_LINESIZE
:
295 case _SC_LEVEL2_CACHE_SIZE
:
296 return (ecx
& 0xf000) == 0 ? 0 : (ecx
>> 6) & 0x3fffc00;
298 case _SC_LEVEL2_CACHE_ASSOC
:
299 switch ((ecx
>> 12) & 0xf)
305 return (ecx
>> 12) & 0xf;
321 return ((ecx
>> 6) & 0x3fffc00) / (ecx
& 0xff);
327 case _SC_LEVEL2_CACHE_LINESIZE
:
328 return (ecx
& 0xf000) == 0 ? 0 : ecx
& 0xff;
330 case _SC_LEVEL3_CACHE_SIZE
:
331 return (edx
& 0xf000) == 0 ? 0 : (edx
& 0x3ffc0000) << 1;
333 case _SC_LEVEL3_CACHE_ASSOC
:
334 switch ((edx
>> 12) & 0xf)
340 return (edx
>> 12) & 0xf;
356 return ((edx
& 0x3ffc0000) << 1) / (edx
& 0xff);
362 case _SC_LEVEL3_CACHE_LINESIZE
:
363 return (edx
& 0xf000) == 0 ? 0 : edx
& 0xff;
366 assert (! "cannot happen");
372 /* Get the value of the system variable NAME. */
375 __cache_sysconf (int name
)
377 /* Find out what brand of processor. */
382 asm volatile ("cpuid"
383 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
386 /* This spells out "GenuineIntel". */
387 if (ebx
== 0x756e6547 && ecx
== 0x6c65746e && edx
== 0x49656e69)
388 return handle_intel (name
, eax
);
390 /* This spells out "AuthenticAMD". */
391 if (ebx
== 0x68747541 && ecx
== 0x444d4163 && edx
== 0x69746e65)
392 return handle_amd (name
);
394 // XXX Fill in more vendors.
396 /* CPU not known, we have no information. */
401 /* Half the data cache size for use in memory and string routines, typically
403 long int __x86_64_data_cache_size_half attribute_hidden
= 32 * 1024 / 2;
404 /* Shared cache size for use in memory and string routines, typically
406 long int __x86_64_shared_cache_size_half attribute_hidden
= 1024 * 1024 / 2;
407 /* PREFETCHW support flag for use in memory and string routines. */
408 int __x86_64_prefetchw attribute_hidden
;
412 __attribute__((constructor
))
413 init_cacheinfo (void)
415 /* Find out what brand of processor. */
423 long int shared
= -1;
425 unsigned int threads
= 0;
427 asm volatile ("cpuid"
428 : "=a" (max_cpuid
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
431 /* This spells out "GenuineIntel". */
432 if (ebx
== 0x756e6547 && ecx
== 0x6c65746e && edx
== 0x49656e69)
434 data
= handle_intel (_SC_LEVEL1_DCACHE_SIZE
, max_cpuid
);
438 shared
= handle_intel (_SC_LEVEL3_CACHE_SIZE
, max_cpuid
);
442 /* Try L2 otherwise. */
444 shared
= handle_intel (_SC_LEVEL2_CACHE_SIZE
, max_cpuid
);
447 /* Figure out the number of logical threads that share the
448 highest cache level. */
453 /* Query until desired cache level is enumerated. */
456 asm volatile ("cpuid"
457 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
458 : "0" (4), "2" (i
++));
460 /* There seems to be a bug in at least some Pentium Ds
461 which sometimes fail to iterate all cache parameters.
462 Do not loop indefinitely here, stop in this case and
463 assume there is no such information. */
464 if ((eax
& 0x1f) == 0)
465 goto intel_bug_no_cache_info
;
467 while (((eax
>> 5) & 0x7) != level
);
469 threads
= ((eax
>> 14) & 0x3ff) + 1;
473 intel_bug_no_cache_info
:
474 /* Assume that all logical threads share the highest cache level. */
475 asm volatile ("cpuid"
476 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
479 threads
= (ebx
>> 16) & 0xff;
482 /* Cap usage of highest cache level to the number of supported
484 if (shared
> 0 && threads
> 0)
487 /* This spells out "AuthenticAMD". */
488 else if (ebx
== 0x68747541 && ecx
== 0x444d4163 && edx
== 0x69746e65)
490 data
= handle_amd (_SC_LEVEL1_DCACHE_SIZE
);
491 long int core
= handle_amd (_SC_LEVEL2_CACHE_SIZE
);
492 shared
= handle_amd (_SC_LEVEL3_CACHE_SIZE
);
494 /* Get maximum extended function. */
495 asm volatile ("cpuid"
496 : "=a" (max_cpuid_ex
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
500 /* No shared L3 cache. All we have is the L2 cache. */
504 /* Figure out the number of logical threads that share L3. */
505 if (max_cpuid_ex
>= 0x80000008)
507 /* Get width of APIC ID. */
508 asm volatile ("cpuid"
509 : "=a" (max_cpuid_ex
), "=b" (ebx
), "=c" (ecx
),
512 threads
= 1 << ((ecx
>> 12) & 0x0f);
517 /* If APIC ID width is not available, use logical
519 asm volatile ("cpuid"
520 : "=a" (max_cpuid_ex
), "=b" (ebx
), "=c" (ecx
),
524 if ((edx
& (1 << 28)) != 0)
525 threads
= (ebx
>> 16) & 0xff;
528 /* Cap usage of highest cache level to the number of
529 supported threads. */
533 /* Account for exclusive L2 and L3 caches. */
537 if (max_cpuid_ex
>= 0x80000001)
539 asm volatile ("cpuid"
540 : "=a" (eax
), "=b" (ebx
), "=c" (ecx
), "=d" (edx
)
542 /* PREFETCHW || 3DNow! */
543 if ((ecx
& 0x100) || (edx
& 0x80000000))
544 __x86_64_prefetchw
= -1;
549 __x86_64_data_cache_size_half
= data
/ 2;
552 __x86_64_shared_cache_size_half
= shared
/ 2;