2011-03-22 Ulrich Drepper * sysdeps/unix/sysv/linux/i386/sysconf.c (intel_check_word): Increment round counter. * sysdeps/x86_64/cacheinfo.c (intel_check_word): Likewise. 2011-03-20 Ulrich Drepper [BZ #12587] * sysdeps/unix/sysv/linux/i386/sysconf.c (intel_check_word): Handle cache information in CPU leaf 4. * sysdeps/x86_64/cacheinfo.c (intel_check_word): Likewise. Index: glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/i386/sysconf.c =================================================================== --- glibc-2.12-2-gc4ccff1.orig/sysdeps/unix/sysv/linux/i386/sysconf.c +++ glibc-2.12-2-gc4ccff1/sysdeps/unix/sysv/linux/i386/sysconf.c @@ -186,6 +186,57 @@ intel_check_word (int name, unsigned int /* No need to look further. */ break; } + else if (byte == 0xff) + { + /* CPUID leaf 0x4 contains all the information. We need to + iterate over it. */ + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + + unsigned int round = 0; + while (1) + { + asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" + : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) + : "0" (4), "2" (round)); + + enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f; + if (type == null) + /* That was the end. */ + break; + + unsigned int level = (eax >> 5) & 0x7; + + if ((level == 1 && type == data + && folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE)) + || (level == 1 && type == inst + && folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE)) + || (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE)) + || (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) + || (level == 4 && folded_rel_name == M(_SC_LEVEL4_CACHE_SIZE))) + { + unsigned int offset = M(name) - folded_rel_name; + + if (offset == 0) + /* Cache size. */ + return (((ebx >> 22) + 1) + * (((ebx >> 12) & 0x3ff) + 1) + * ((ebx & 0xfff) + 1) + * (ecx + 1)); + if (offset == 1) + return (ebx >> 22) + 1; + + assert (offset == 2); + return (ebx & 0xfff) + 1; + } + + ++round; + } + /* There is no other cache information anywhere else. */ + break; + } else { if (byte == 0x49 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) Index: glibc-2.12-2-gc4ccff1/sysdeps/x86_64/cacheinfo.c =================================================================== --- glibc-2.12-2-gc4ccff1.orig/sysdeps/x86_64/cacheinfo.c +++ glibc-2.12-2-gc4ccff1/sysdeps/x86_64/cacheinfo.c @@ -181,6 +181,57 @@ intel_check_word (int name, unsigned int /* No need to look further. */ break; } + else if (byte == 0xff) + { + /* CPUID leaf 0x4 contains all the information. We need to + iterate over it. */ + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + + unsigned int round = 0; + while (1) + { + asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" + : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) + : "0" (4), "2" (round)); + + enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f; + if (type == null) + /* That was the end. */ + break; + + unsigned int level = (eax >> 5) & 0x7; + + if ((level == 1 && type == data + && folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE)) + || (level == 1 && type == inst + && folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE)) + || (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE)) + || (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) + || (level == 4 && folded_rel_name == M(_SC_LEVEL4_CACHE_SIZE))) + { + unsigned int offset = M(name) - folded_rel_name; + + if (offset == 0) + /* Cache size. */ + return (((ebx >> 22) + 1) + * (((ebx >> 12) & 0x3ff) + 1) + * ((ebx & 0xfff) + 1) + * (ecx + 1)); + if (offset == 1) + return (ebx >> 22) + 1; + + assert (offset == 2); + return (ebx & 0xfff) + 1; + } + + ++round; + } + /* There is no other cache information anywhere else. */ + break; + } else { if (byte == 0x49 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))