summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2006-11-06 04:59:30 +0000
committerUlrich Drepper <drepper@redhat.com>2006-11-06 04:59:30 +0000
commitee6815e76c19f805229f4dbfd4ec27de1bb9864f (patch)
treec4d2f6a652367e9ec8c34a286c96b90c8c177be0
parent9666e36c186323b3f9fa6efe05cf6095a599083a (diff)
* sysdeps/unix/sysv/linux/i386/sysconf.c (intel_check_word):
Update handling of cache descriptor 0x49 for new models. * sysdeps/unix/sysv/linux/x86_64/sysconf.c (intel_check_word): Likewise.
-rw-r--r--ChangeLog7
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysconf.c29
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/sysconf.c29
3 files changed, 63 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index c5c8a4b8c7..be5432c8b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-11-05 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/unix/sysv/linux/i386/sysconf.c (intel_check_word):
+ Update handling of cache descriptor 0x49 for new models.
+ * sysdeps/unix/sysv/linux/x86_64/sysconf.c (intel_check_word):
+ Likewise.
+
2006-11-02 Jakub Jelinek <jakub@redhat.com>
* malloc/memusage.c (dest): Reset not_me back to false after
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;