This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: PR libc/12587: sysconf(_SC_*CACHE) returns 0 for all cacheson some CPUs


Hi,

Fix for

http://sourceware.org/bugzilla/show_bug.cgi?id=12587

doesn't work since the loop may not terminate.  It goes into an infinite
loop on Xeon X5670.  Also we should use __cpuid_count like the rest of
sysdeps/x86_64/cacheinfo.c.  With this patch, I got

LEVEL1_ICACHE_SIZE                 32768
LEVEL1_ICACHE_ASSOC                4
LEVEL1_ICACHE_LINESIZE             64
LEVEL1_DCACHE_SIZE                 32768
LEVEL1_DCACHE_ASSOC                8
LEVEL1_DCACHE_LINESIZE             64
LEVEL2_CACHE_SIZE                  262144
LEVEL2_CACHE_ASSOC                 8
LEVEL2_CACHE_LINESIZE              64
LEVEL3_CACHE_SIZE                  12582912
LEVEL3_CACHE_ASSOC                 16
LEVEL3_CACHE_LINESIZE              64
LEVEL4_CACHE_SIZE                  0
LEVEL4_CACHE_ASSOC                 0
LEVEL4_CACHE_LINESIZE              0

H.J.
--
2011-03-22  H.J. Lu  <hongjiu.lu@intel.com>

	PR libc/12587
	* sysdeps/unix/sysv/linux/i386/sysconf.c: Include <cpuid.h>.
	(__cpuid_count): New.
	(intel_check_word): Use __cpuid_count and increment round.
	* sysdeps/x86_64/cacheinfo.c (intel_check_word): Likewise.

diff --git a/sysdeps/unix/sysv/linux/i386/sysconf.c b/sysdeps/unix/sysv/linux/i386/sysconf.c
index 4ea1a2b..540bdd5 100644
--- a/sysdeps/unix/sysv/linux/i386/sysconf.c
+++ b/sysdeps/unix/sysv/linux/i386/sysconf.c
@@ -22,6 +22,26 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <hp-timing.h>
+#include <cpuid.h>
+
+#ifndef __cpuid_count
+/* FIXME: Provide __cpuid_count if it isn't defined.  Copied from gcc
+   4.4.0.  Remove this if gcc 4.4 is the minimum requirement.  */
+# if defined(__i386__) && defined(__PIC__)
+/* %ebx may be the PIC register.  */
+#  define __cpuid_count(level, count, a, b, c, d)		\
+  __asm__ ("xchg{l}\t{%%}ebx, %1\n\t"			\
+	   "cpuid\n\t"					\
+	   "xchg{l}\t{%%}ebx, %1\n\t"			\
+	   : "=a" (a), "=r" (b), "=c" (c), "=d" (d)	\
+	   : "0" (level), "2" (count))
+# else
+#  define __cpuid_count(level, count, a, b, c, d)		\
+  __asm__ ("cpuid\n\t"					\
+	   : "=a" (a), "=b" (b), "=c" (c), "=d" (d)	\
+	   : "0" (level), "2" (count))
+# endif
+#endif
 
 static long int linux_sysconf (int name);
 
@@ -198,9 +218,7 @@ intel_check_word (int name, unsigned int value, bool *has_level_2,
 	  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));
+	      __cpuid_count (4, round++, eax, ebx, ecx, edx);
 
 	      enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f;
 	      if (type == null)
diff --git a/sysdeps/x86_64/cacheinfo.c b/sysdeps/x86_64/cacheinfo.c
index fdd6427..2d33508 100644
--- a/sysdeps/x86_64/cacheinfo.c
+++ b/sysdeps/x86_64/cacheinfo.c
@@ -193,9 +193,7 @@ intel_check_word (int name, unsigned int value, bool *has_level_2,
 	  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));
+	      __cpuid_count (4, round++, eax, ebx, ecx, edx);
 
 	      enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f;
 	      if (type == null)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]