about summary refs log tree commit diff
path: root/sysdeps/unix
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-11-09 19:57:49 +0000
committerJakub Jelinek <jakub@redhat.com>2006-11-09 19:57:49 +0000
commitdddf300c357a38a1d26a97ade2e905a0f85befe3 (patch)
tree216f66ce0825df1efaa3ffa64527ee5f924bf8e9 /sysdeps/unix
parent2c72abb4969f2b376a5e58c88424bd3b9c9c70b5 (diff)
downloadglibc-dddf300c357a38a1d26a97ade2e905a0f85befe3.tar.gz
glibc-dddf300c357a38a1d26a97ade2e905a0f85befe3.tar.xz
glibc-dddf300c357a38a1d26a97ade2e905a0f85befe3.zip
Updated to fedora-glibc-20061109T1949
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysconf.c29
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/sysconf.c29
2 files changed, 56 insertions, 2 deletions
diff --git a/sysdeps/unix/sysv/linux/i386/sysconf.c b/sysdeps/unix/sysv/linux/i386/sysconf.c
index 25b9ba734e..c9d7f77a00 100644
--- a/sysdeps/unix/sysv/linux/i386/sysconf.c
+++ b/sysdeps/unix/sysv/linux/i386/sysconf.c
@@ -97,7 +97,7 @@ static const struct intel_02_cache_info
     { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 },
     { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 },
     { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 },
-    { 0x49, _SC_LEVEL3_CACHE_SIZE, 4194304, 16, 64 },
+    { 0x49, _SC_LEVEL2_CACHE_SIZE, 4194304, 16, 64 },
     { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 },
     { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 },
     { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 },
@@ -166,6 +166,33 @@ intel_check_word (int name, unsigned int value, bool *has_level_2,
 	}
       else
 	{
+	  if (byte == 0x49 && folded_name == _SC_LEVEL3_CACHE_SIZE)
+	    {
+	      /* Intel reused this value.  For family 15, model 6 it
+		 specifies the 3rd level cache.  Otherwise the 2nd
+		 level cache.  */
+	      unsigned int eax;
+	      unsigned int ebx;
+	      unsigned int ecx;
+	      unsigned int edx;
+	      asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+			    : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+			    : "0" (1));
+
+	      unsigned int family = ((eax >> 20) & 0xff) + ((eax >> 8) & 0xf);
+	      unsigned int model = ((((eax >>16) & 0xf) << 4)
+				    + ((eax >> 4) & 0xf));
+	      if (family == 15 && model == 6)
+		{
+		  /* The level 3 cache is encoded for this model like
+		     the level 2 cache is for other models.  Pretend
+		     the caller asked for the level 2 cache.  */
+		  name = (_SC_LEVEL2_CACHE_SIZE
+			  + (name - _SC_LEVEL3_CACHE_SIZE));
+		  folded_name = _SC_LEVEL3_CACHE_SIZE;
+		}
+	    }
+
 	  struct intel_02_cache_info *found;
 	  struct intel_02_cache_info search;
 
diff --git a/sysdeps/unix/sysv/linux/x86_64/sysconf.c b/sysdeps/unix/sysv/linux/x86_64/sysconf.c
index 726c5e33ac..80c982aa3b 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sysconf.c
+++ b/sysdeps/unix/sysv/linux/x86_64/sysconf.c
@@ -58,7 +58,7 @@ static const struct intel_02_cache_info
     { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 },
     { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 },
     { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 },
-    { 0x49, _SC_LEVEL3_CACHE_SIZE, 4194304, 16, 64 },
+    { 0x49, _SC_LEVEL2_CACHE_SIZE, 4194304, 16, 64 },
     { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 },
     { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 },
     { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 },
@@ -127,6 +127,33 @@ intel_check_word (int name, unsigned int value, bool *has_level_2,
 	}
       else
 	{
+	  if (byte == 0x49 && folded_name == _SC_LEVEL3_CACHE_SIZE)
+	    {
+	      /* Intel reused this value.  For family 15, model 6 it
+		 specifies the 3rd level cache.  Otherwise the 2nd
+		 level cache.  */
+	      unsigned int eax;
+	      unsigned int ebx;
+	      unsigned int ecx;
+	      unsigned int edx;
+	      asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+			    : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+			    : "0" (1));
+
+	      unsigned int family = ((eax >> 20) & 0xff) + ((eax >> 8) & 0xf);
+	      unsigned int model = ((((eax >>16) & 0xf) << 4)
+				    + ((eax >> 4) & 0xf));
+	      if (family == 15 && model == 6)
+		{
+		  /* The level 3 cache is encoded for this model like
+		     the level 2 cache is for other models.  Pretend
+		     the caller asked for the level 2 cache.  */
+		  name = (_SC_LEVEL2_CACHE_SIZE
+			  + (name - _SC_LEVEL3_CACHE_SIZE));
+		  folded_name = _SC_LEVEL3_CACHE_SIZE;
+		}
+	    }
+
 	  struct intel_02_cache_info *found;
 	  struct intel_02_cache_info search;