[PATCH 1/3] cpufrequtils aperf: Add cpuid support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Linux Kernel Devel]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Forum]     [Linux SCSI]

  Powered by Linux