| From 2b92865e648ce04a39fda4f903784a5d01ecb0dc Mon Sep 17 00:00:00 2001 |
| From: Josh Triplett <josh@joshtriplett.org> |
| Date: Tue, 20 Aug 2013 17:20:14 -0700 |
| Subject: turbostat: Use GCC's CPUID functions to support PIC |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| From: Josh Triplett <josh@joshtriplett.org> |
| |
| commit 2b92865e648ce04a39fda4f903784a5d01ecb0dc upstream. |
| |
| 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 <josh@joshtriplett.org> |
| Signed-off-by: Len Brown <len.brown@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| tools/power/x86/turbostat/turbostat.c | 11 ++++++----- |
| 1 file changed, 6 insertions(+), 5 deletions(-) |
| |
| --- a/tools/power/x86/turbostat/turbostat.c |
| +++ b/tools/power/x86/turbostat/turbostat.c |
| @@ -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 */ |
| @@ -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; |
| @@ -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; |
| @@ -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); |
| @@ -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) { |
| @@ -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); |