Skip to content

Commit

Permalink
Implement x86 cpuid handling of leaf4 for cache information.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ulrich Drepper committed Mar 20, 2011
1 parent 042c49c commit 2a11560
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 9 deletions.
7 changes: 7 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
2011-03-20 Ulrich Drepper <drepper@gmail.com>

[BZ #12587]
* sysdeps/unix/sysv/linux/i386/sysconf.c (intel_check_word):
Handle cache information in CPU leaf 4.
* sysdeps/x86_64/cacheinfo.c (intel_check_word): Likewise.

2011-03-18 Ulrich Drepper <drepper@gmail.com>

[BZ #12583]
Expand Down
4 changes: 2 additions & 2 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
GNU C Library NEWS -- history of user-visible changes. 2011-3-18
GNU C Library NEWS -- history of user-visible changes. 2011-3-20
Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
See the end for copying conditions.

Expand All @@ -9,7 +9,7 @@ Version 2.14

* The following bugs are resolved with this release:

11724, 12445, 12454, 12460, 12469, 12489, 12509, 12510, 12583
11724, 12445, 12454, 12460, 12469, 12489, 12509, 12510, 12583, 12587

Version 2.13

Expand Down
63 changes: 56 additions & 7 deletions sysdeps/unix/sysv/linux/i386/sysconf.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Get file-specific information about a file. Linux version.
Copyright (C) 2003, 2004, 2006, 2007, 2009 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2006, 2007, 2009, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
Expand Down Expand Up @@ -186,6 +186,55 @@ intel_check_word (int name, unsigned int value, bool *has_level_2,
/* No need to look further. */
break;
}
else if (byte == 0xff)
{
/* CPUID leaf 0x4 contains all the information. We need to
iterate over it. */
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;

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));

enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f;
if (type == null)
/* That was the end. */
break;

unsigned int level = (eax >> 5) & 0x7;

if ((level == 1 && type == data
&& folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE))
|| (level == 1 && type == inst
&& folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE))
|| (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE))
|| (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))
|| (level == 4 && folded_rel_name == M(_SC_LEVEL4_CACHE_SIZE)))
{
unsigned int offset = M(name) - folded_rel_name;

if (offset == 0)
/* Cache size. */
return (((ebx >> 22) + 1)
* (((ebx >> 12) & 0x3ff) + 1)
* ((ebx & 0xfff) + 1)
* (ecx + 1));
if (offset == 1)
return (ebx >> 22) + 1;

assert (offset == 2);
return (ebx & 0xfff) + 1;
}
}
/* There is no other cache information anywhere else. */
break;
}
else
{
if (byte == 0x49 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))
Expand Down Expand Up @@ -358,11 +407,11 @@ handle_amd (int name)
case _SC_LEVEL2_CACHE_ASSOC:
ecx >>= 12;
switch (ecx & 0xf)
{
case 0:
case 1:
case 2:
case 4:
{
case 0:
case 1:
case 2:
case 4:
return ecx & 0xf;
case 6:
return 8;
Expand All @@ -372,7 +421,7 @@ handle_amd (int name)
return (ecx << 6) & 0x3fffc00;
default:
return 0;
}
}
case _SC_LEVEL2_CACHE_LINESIZE:
return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
default:
Expand Down
49 changes: 49 additions & 0 deletions sysdeps/x86_64/cacheinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,55 @@ intel_check_word (int name, unsigned int value, bool *has_level_2,
/* No need to look further. */
break;
}
else if (byte == 0xff)
{
/* CPUID leaf 0x4 contains all the information. We need to
iterate over it. */
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;

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));

enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f;
if (type == null)
/* That was the end. */
break;

unsigned int level = (eax >> 5) & 0x7;

if ((level == 1 && type == data
&& folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE))
|| (level == 1 && type == inst
&& folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE))
|| (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE))
|| (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))
|| (level == 4 && folded_rel_name == M(_SC_LEVEL4_CACHE_SIZE)))
{
unsigned int offset = M(name) - folded_rel_name;

if (offset == 0)
/* Cache size. */
return (((ebx >> 22) + 1)
* (((ebx >> 12) & 0x3ff) + 1)
* ((ebx & 0xfff) + 1)
* (ecx + 1));
if (offset == 1)
return (ebx >> 22) + 1;

assert (offset == 2);
return (ebx & 0xfff) + 1;
}
}
/* There is no other cache information anywhere else. */
break;
}
else
{
if (byte == 0x49 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))
Expand Down

0 comments on commit 2a11560

Please sign in to comment.