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