From 58101473df84b017e23c11ce0ccfb74a0766eb7a Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 15 Mar 2004 06:23:52 +0000 Subject: Update. 2004-03-13 Jakub Jelinek * 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. --- ChangeLog | 8 ++++ sysdeps/unix/sysv/linux/i386/sysconf.c | 78 +++++++++++++++++++++++++++++++- sysdeps/unix/sysv/linux/x86_64/sysconf.c | 78 +++++++++++++++++++++++++++++++- 3 files changed, 160 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6a8f7fe78e..71f7fb52a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2004-03-13 Jakub Jelinek + + * 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. + 2004-03-14 Ulrich Drepper * wcsmbs/mbsrtowcs.c: Just a wrapper around __mbsrtowcs_l. diff --git a/sysdeps/unix/sysv/linux/i386/sysconf.c b/sysdeps/unix/sysv/linux/i386/sysconf.c index 54e78409d4..cb4706de73 100644 --- a/sysdeps/unix/sysv/linux/i386/sysconf.c +++ b/sysdeps/unix/sysv/linux/i386/sysconf.c @@ -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 maxidx) } +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. */ diff --git a/sysdeps/unix/sysv/linux/x86_64/sysconf.c b/sysdeps/unix/sysv/linux/x86_64/sysconf.c index ab777ba0cd..87f2c451f3 100644 --- a/sysdeps/unix/sysv/linux/x86_64/sysconf.c +++ b/sysdeps/unix/sysv/linux/x86_64/sysconf.c @@ -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 maxidx) } +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. */ -- cgit 1.4.1