7 #include "helpers/helpers.h"
9 static const char *cpu_vendor_table[X86_VENDOR_MAX] = {
10 "Unknown", "GenuineIntel", "AuthenticAMD",
13 #if defined(__i386__) || defined(__x86_64__)
19 * CPUID functions returning a single datum
21 * Define unsigned int cpuid_e[abcd]x(unsigned int op)
23 #define cpuid_func(reg) \
24 unsigned int cpuid_##reg(unsigned int op) \
26 unsigned int eax, ebx, ecx, edx; \
27 __cpuid(op, eax, ebx, ecx, edx); \
35 #endif /* defined(__i386__) || defined(__x86_64__) */
39 * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
41 * Returns 0 on success or a negativ error code
43 * TBD: Should there be a cpuid alternative for this if /proc is not mounted?
45 int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info)
50 unsigned int unknown = 0xffffff;
51 unsigned int cpuid_level, ext_cpuid_level;
55 cpu_info->vendor = X86_VENDOR_UNKNOWN;
56 cpu_info->family = unknown;
57 cpu_info->model = unknown;
58 cpu_info->stepping = unknown;
61 fp = fopen("/proc/cpuinfo", "r");
66 if (!fgets(value, 64, fp))
70 if (!strncmp(value, "processor\t: ", 12)) {
71 sscanf(value, "processor\t: %u", &proc);
77 if (!strncmp(value, "vendor_id", 9))
78 for (x = 1; x < X86_VENDOR_MAX; x++) {
79 if (strstr(value, cpu_vendor_table[x]))
82 /* Get CPU family, etc. */
83 else if (!strncmp(value, "cpu family\t: ", 13)) {
84 sscanf(value, "cpu family\t: %u",
87 else if (!strncmp(value, "model\t\t: ", 9)) {
88 sscanf(value, "model\t\t: %u",
91 else if (!strncmp(value, "stepping\t: ", 10)) {
92 sscanf(value, "stepping\t: %u",
95 /* Exit -> all values must have been set */
96 if (cpu_info->vendor == X86_VENDOR_UNKNOWN ||
97 cpu_info->family == unknown ||
98 cpu_info->model == unknown ||
99 cpu_info->stepping == unknown) {
111 /* Get some useful CPU capabilities from cpuid */
112 if (cpu_info->vendor != X86_VENDOR_AMD &&
113 cpu_info->vendor != X86_VENDOR_INTEL)
116 cpuid_level = cpuid_eax(0);
117 ext_cpuid_level = cpuid_eax(0x80000000);
120 if (ext_cpuid_level >= 0x80000007 &&
121 (cpuid_edx(0x80000007) & (1 << 8)))
122 cpu_info->caps |= CPUPOWER_CAP_INV_TSC;
124 /* Aperf/Mperf registers support */
125 if (cpuid_level >= 6 && (cpuid_ecx(6) & 0x1))
126 cpu_info->caps |= CPUPOWER_CAP_APERF;
128 /* AMD Boost state enable/disable register */
129 if (cpu_info->vendor == X86_VENDOR_AMD) {
130 if (ext_cpuid_level >= 0x80000007 &&
131 (cpuid_edx(0x80000007) & (1 << 9)))
132 cpu_info->caps |= CPUPOWER_CAP_AMD_CBP;
135 /* Intel's perf-bias MSR support */
136 if (cpu_info->vendor == X86_VENDOR_INTEL) {
137 if (cpuid_level >= 6 && (cpuid_ecx(6) & (1 << 3)))
138 cpu_info->caps |= CPUPOWER_CAP_PERF_BIAS;
141 /* printf("ID: %u - Extid: 0x%x - Caps: 0x%llx\n",
142 cpuid_level, ext_cpuid_level, cpu_info->caps);