aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <borislav.petkov@amd.com>2010-04-29 13:46:43 +0200
committerDominik Brodowski <linux@dominikbrodowski.net>2010-04-29 16:52:05 +0200
commit6396da3821b552d4b7a5b36f772ca2801b4ca2e7 (patch)
tree547b6f378da5af1ed0975b44d994fe29953e92a9
parent73f8d82f6a94c1179a7a7a60a1d5988194e4c166 (diff)
downloadcpufrequtils-6396da3821b552d4b7a5b36f772ca2801b4ca2e7.tar.gz
cpufrequtils aperf: Add cpuid support
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@amd.com> Signed-off-by: Thomas Renninger <trenn@suse.de> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-rw-r--r--utils/aperf.c27
-rw-r--r--utils/cpuid.h63
2 files changed, 70 insertions, 20 deletions
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 */