* [PATCH] Handle AMD CPUs in sysconf (_SC_LEVEL*)
@ 2004-03-13 14:09 Jakub Jelinek
2004-03-15 3:45 ` Ulrich Drepper
0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2004-03-13 14:09 UTC (permalink / raw)
To: Ulrich Drepper; +Cc: Glibc hackers
Hi!
I'm not entirely sure when sysconf (_SC_LEVEL*) should return 0 and when
-1 without errno set, other than that this seems to work both on
Opteron 144 and oldish Athlon.
2004-03-13 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/i386/sysconf.c (intel_02_known): Add const.
(handle_amd): New function.
(__sysconf): Handle _SC_LEVEL4_CACHE_LINESIZE here, not in
linux_sysconf. Call handle_amd on AuthenticAMD.
* sysdeps/unix/sysv/linux/x86_64/sysconf.c: Likewise.
--- libc/sysdeps/unix/sysv/linux/i386/sysconf.c.jj 2004-03-13 15:02:24.686868696 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/sysconf.c 2004-03-13 15:02:01.094092806 +0100
@@ -65,7 +65,7 @@ handle_i486 (int name)
}
-static struct intel_02_cache_info
+static const struct intel_02_cache_info
{
unsigned int idx;
int name;
@@ -250,12 +250,81 @@ handle_intel (int name, unsigned int max
}
+static long int
+handle_amd (int name)
+{
+ 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" (0x80000000));
+
+ if (name >= _SC_LEVEL3_CACHE_SIZE)
+ return 0;
+
+ unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE);
+ if (eax < fn)
+ return 0;
+
+ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+ : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+ : "0" (fn));
+
+ if (name < _SC_LEVEL1_DCACHE_SIZE)
+ {
+ name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE;
+ ecx = edx;
+ }
+
+ switch (name)
+ {
+ case _SC_LEVEL1_DCACHE_SIZE:
+ return (ecx >> 14) & 0x3fc00;
+ case _SC_LEVEL1_DCACHE_ASSOC:
+ ecx >>= 16;
+ if ((ecx & 0xff) == 0xff)
+ /* Fully associative. */
+ return (ecx << 2) & 0x3fc00;
+ return ecx & 0xff;
+ case _SC_LEVEL1_DCACHE_LINESIZE:
+ return ecx & 0xff;
+ case _SC_LEVEL2_CACHE_SIZE:
+ return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00;
+ case _SC_LEVEL2_CACHE_ASSOC:
+ ecx >>= 12;
+ switch (ecx & 0xf)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ return ecx & 0xf;
+ case 6:
+ return 8;
+ case 8:
+ return 16;
+ case 0xf:
+ return (ecx << 6) & 0x3fffc00;
+ default:
+ return 0;
+ }
+ case _SC_LEVEL2_CACHE_LINESIZE:
+ return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
+ default:
+ assert (! "cannot happen");
+ }
+ return -1;
+}
+
+
/* Get the value of the system variable NAME. */
long int
__sysconf (int name)
{
/* We only handle the cache information here (for now). */
- if (name < _SC_LEVEL1_ICACHE_SIZE || name > _SC_LEVEL4_CACHE_ASSOC)
+ if (name < _SC_LEVEL1_ICACHE_SIZE || name > _SC_LEVEL4_CACHE_LINESIZE)
return linux_sysconf (name);
/* Recognize i386 and compatible. These don't have any cache on
@@ -299,6 +368,11 @@ __sysconf (int name)
/* This spells out "GenuineIntel". */
if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
return handle_intel (name, eax);
+
+ /* This spells out "AuthenticAMD". */
+ if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
+ return handle_amd (name);
+
// XXX Fill in more vendors.
/* CPU not known, we have no information. */
--- libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c.jj 2004-03-12 22:34:19.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c 2004-03-13 14:59:54.223807899 +0100
@@ -26,7 +26,7 @@
static long int linux_sysconf (int name);
-static struct intel_02_cache_info
+static const struct intel_02_cache_info
{
unsigned int idx;
int name;
@@ -206,12 +206,81 @@ handle_intel (int name, unsigned int max
}
+static long int
+handle_amd (int name)
+{
+ 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" (0x80000000));
+
+ if (name >= _SC_LEVEL3_CACHE_SIZE)
+ return 0;
+
+ unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE);
+ if (eax < fn)
+ return 0;
+
+ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+ : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+ : "0" (fn));
+
+ if (name < _SC_LEVEL1_DCACHE_SIZE)
+ {
+ name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE;
+ ecx = edx;
+ }
+
+ switch (name)
+ {
+ case _SC_LEVEL1_DCACHE_SIZE:
+ return (ecx >> 14) & 0x3fc00;
+ case _SC_LEVEL1_DCACHE_ASSOC:
+ ecx >>= 16;
+ if ((ecx & 0xff) == 0xff)
+ /* Fully associative. */
+ return (ecx << 2) & 0x3fc00;
+ return ecx & 0xff;
+ case _SC_LEVEL1_DCACHE_LINESIZE:
+ return ecx & 0xff;
+ case _SC_LEVEL2_CACHE_SIZE:
+ return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00;
+ case _SC_LEVEL2_CACHE_ASSOC:
+ ecx >>= 12;
+ switch (ecx & 0xf)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ return ecx & 0xf;
+ case 6:
+ return 8;
+ case 8:
+ return 16;
+ case 0xf:
+ return (ecx << 6) & 0x3fffc00;
+ default:
+ return 0;
+ }
+ case _SC_LEVEL2_CACHE_LINESIZE:
+ return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
+ default:
+ assert (! "cannot happen");
+ }
+ return -1;
+}
+
+
/* Get the value of the system variable NAME. */
long int
__sysconf (int name)
{
/* We only handle the cache information here (for now). */
- if (name < _SC_LEVEL1_ICACHE_SIZE || name > _SC_LEVEL4_CACHE_ASSOC)
+ if (name < _SC_LEVEL1_ICACHE_SIZE || name > _SC_LEVEL4_CACHE_LINESIZE)
return linux_sysconf (name);
/* Find out what brand of processor. */
@@ -226,6 +295,11 @@ __sysconf (int name)
/* This spells out "GenuineIntel". */
if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
return handle_intel (name, eax);
+
+ /* This spells out "AuthenticAMD". */
+ if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
+ return handle_amd (name);
+
// XXX Fill in more vendors.
/* CPU not known, we have no information. */
Jakub
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] Handle AMD CPUs in sysconf (_SC_LEVEL*)
2004-03-13 14:09 [PATCH] Handle AMD CPUs in sysconf (_SC_LEVEL*) Jakub Jelinek
@ 2004-03-15 3:45 ` Ulrich Drepper
0 siblings, 0 replies; 2+ messages in thread
From: Ulrich Drepper @ 2004-03-15 3:45 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: Glibc hackers
Applied.
--
⧠Ulrich Drepper ⧠Red Hat, Inc. ⧠444 Castro St ⧠Mountain View, CA â
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2004-03-15 3:45 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-03-13 14:09 [PATCH] Handle AMD CPUs in sysconf (_SC_LEVEL*) Jakub Jelinek
2004-03-15 3:45 ` Ulrich Drepper
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).