From: Borislav Petkov <borislav.petkov@xxxxxxx> Add cpuid() helpers blatantly stolen from the kernel sources and use that for checking for aperf/mperf support instead of accessing "/dev/cpu/%d/cpuid" which requires the module to be enabled on the target system. Signed-off-by: Borislav Petkov <borislav.petkov@xxxxxxx> Signed-off-by: Thomas Renninger <trenn@xxxxxxx> CC: cpufreq@xxxxxxxxxxxxxxx CC: linux@xxxxxxxxxxxxxxxxxxxx --- utils/aperf.c | 27 ++++++------------------ utils/cpuid.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 20 deletions(-) create mode 100644 utils/cpuid.h diff --git a/utils/aperf.c b/utils/aperf.c index 8ecff2c..17e1cb6 100644 --- a/utils/aperf.c +++ b/utils/aperf.c @@ -54,6 +54,7 @@ #include <string.h> #include "cpufreq.h" +#include "cpuid.h" #define MSR_IA32_APERF 0x000000E8 #define MSR_IA32_MPERF 0x000000E7 @@ -101,27 +102,13 @@ static unsigned int count_cpus(void) return (ret+1); } -static int has_mperf_aperf_support(int cpu) +static int cpu_has_effective_freq() { - int fd; - char msr_file_name[64]; - uint32_t words[4]; - int support; + /* largest base level */ + if (cpuid_eax(0) < 6) + return 0; - sprintf(msr_file_name, "/dev/cpu/%d/cpuid", cpu); - fd = open(msr_file_name, O_RDONLY); - if (fd < 0) - return -1; - if (lseek(fd, 6, SEEK_CUR) == -1) - goto err; - if (read(fd, words, 16) != 16) - goto err; - support = words[2] & 0x1; - close(fd); - return support; - err: - close(fd); - return -1; + return cpuid_ecx(6) & 0x1; } /* @@ -251,7 +238,7 @@ static int get_measure_start_info(unsigned int cpu, cpu_info->is_valid = 0; - ret = has_mperf_aperf_support(cpu); + ret = cpu_has_effective_freq(); if (ret < 0) { fprintf(stderr, "Could not read cpuid, is the cpuid " "driver loaded or compiled into the kernel?\n"); diff --git a/utils/cpuid.h b/utils/cpuid.h new file mode 100644 index 0000000..2bac69a --- /dev/null +++ b/utils/cpuid.h @@ -0,0 +1,63 @@ +#ifndef _CPUFREQ_CPUID_H +#define _CPUFREQ_CPUID_H + +static inline void __cpuid(unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + /* ecx is often an input as well as an output. */ + asm volatile("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (*eax), "2" (*ecx)); +} +static inline void cpuid(unsigned int op, + unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + *eax = op; + *ecx = 0; + __cpuid(eax, ebx, ecx, edx); +} + +/* + * CPUID functions returning a single datum + */ +static inline unsigned int cpuid_eax(unsigned int op) +{ + unsigned int eax, ebx, ecx, edx; + + cpuid(op, &eax, &ebx, &ecx, &edx); + + return eax; +} + +static inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int eax, ebx, ecx, edx; + + cpuid(op, &eax, &ebx, &ecx, &edx); + + return ebx; +} + +static inline unsigned int cpuid_ecx(unsigned int op) +{ + unsigned int eax, ebx, ecx, edx; + + cpuid(op, &eax, &ebx, &ecx, &edx); + + return ecx; +} + +static inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int eax, ebx, ecx, edx; + + cpuid(op, &eax, &ebx, &ecx, &edx); + + return edx; +} + +#endif /* _CPUFREQ_CPUID_H */ -- 1.6.4.2 -- To unsubscribe from this list: send the line "unsubscribe cpufreq" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html