Skip to content

Commit

Permalink
turbostat: Use GCC's CPUID functions to support PIC
Browse files Browse the repository at this point in the history
turbostat uses inline assembly to call cpuid.  On 32-bit x86, on systems
that have certain security features enabled by default that make -fPIC
the default, this causes a build error:

turbostat.c: In function ‘check_cpuid’:
turbostat.c:1906:2: error: PIC register clobbered by ‘ebx’ in ‘asm’
  asm("cpuid" : "=a" (fms), "=c" (ecx), "=d" (edx) : "a" (1) : "ebx");
  ^

GCC provides a header cpuid.h, containing a __get_cpuid function that
works with both PIC and non-PIC.  (On PIC, it saves and restores ebx
around the cpuid instruction.)  Use that instead.

Signed-off-by: Josh Triplett <[email protected]>
Cc: [email protected]
Signed-off-by: Len Brown <[email protected]>
  • Loading branch information
joshtriplett authored and lenb committed Jan 19, 2014
1 parent 2e9c6bc commit 2b92865
Showing 1 changed file with 6 additions and 5 deletions.
11 changes: 6 additions & 5 deletions tools/power/x86/turbostat/turbostat.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <string.h>
#include <ctype.h>
#include <sched.h>
#include <cpuid.h>

char *proc_stat = "/proc/stat";
unsigned int interval_sec = 5; /* set with -i interval_sec */
Expand Down Expand Up @@ -1978,7 +1979,7 @@ void check_cpuid()

eax = ebx = ecx = edx = 0;

asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0));
__get_cpuid(0, &max_level, &ebx, &ecx, &edx);

if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
genuine_intel = 1;
Expand All @@ -1987,7 +1988,7 @@ void check_cpuid()
fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ",
(char *)&ebx, (char *)&edx, (char *)&ecx);

asm("cpuid" : "=a" (fms), "=c" (ecx), "=d" (edx) : "a" (1) : "ebx");
__get_cpuid(1, &fms, &ebx, &ecx, &edx);
family = (fms >> 8) & 0xf;
model = (fms >> 4) & 0xf;
stepping = fms & 0xf;
Expand All @@ -2009,7 +2010,7 @@ void check_cpuid()
* This check is valid for both Intel and AMD.
*/
ebx = ecx = edx = 0;
asm("cpuid" : "=a" (max_level), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000000));
__get_cpuid(0x80000000, &max_level, &ebx, &ecx, &edx);

if (max_level < 0x80000007) {
fprintf(stderr, "CPUID: no invariant TSC (max_level 0x%x)\n", max_level);
Expand All @@ -2020,7 +2021,7 @@ void check_cpuid()
* Non-Stop TSC is advertised by CPUID.EAX=0x80000007: EDX.bit8
* this check is valid for both Intel and AMD
*/
asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000007));
__get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
has_invariant_tsc = edx & (1 << 8);

if (!has_invariant_tsc) {
Expand All @@ -2033,7 +2034,7 @@ void check_cpuid()
* this check is valid for both Intel and AMD
*/

asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x6));
__get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
has_aperf = ecx & (1 << 0);
do_dts = eax & (1 << 0);
do_ptm = eax & (1 << 6);
Expand Down

0 comments on commit 2b92865

Please sign in to comment.