Files
android_kernel_xiaomi_sm8450/tools/power/cpupower/utils/helpers/cpuid.c
Prarit Bhargava d0e4a193c3 tools/power/cpupower: allow running without cpu0
Linux-3.7 added CONFIG_BOOTPARAM_HOTPLUG_CPU0,
allowing systems to offline cpu0.

But when cpu0 is offline, cpupower monitor will not display all
processor and Mperf information:

[root@intel-skylake-dh-03 cpupower]# ./cpupower monitor
WARNING: at least one cpu is offline
    |Idle_Stats
CPU | POLL | C1-S | C1E- | C3-S | C6-S | C7s- | C8-S
   4|  0.00|  0.00|  0.00|  0.00|  0.90|  0.00| 96.13
   1|  0.00|  0.00|  5.49|  0.00|  0.01|  0.00| 92.26
   5|  0.00|  0.00|  0.00|  0.00|  0.46|  0.00| 99.50
   2| 45.42|  0.00|  0.00|  0.00| 22.94|  0.00| 28.84
   6|  0.00| 37.54|  0.00|  0.00|  0.00|  0.00|  0.00
   3|  0.00|  0.00|  0.00|  0.00|  0.30|  0.00| 91.99
   7|  0.00|  0.00|  0.00|  0.00|  4.70|  0.00|  0.70

This patch replaces the hard-coded use of cpu0 in cpupower with the
current cpu, allowing it to run without a cpu0.

After the patch is applied,

[root@intel-skylake-dh-03 cpupower]# ./cpupower monitor
WARNING: at least one cpu is offline
    |Nehalem                    || Mperf              || Idle_Stats
CPU | C3   | C6   | PC3  | PC6  || C0   | Cx   | Freq || POLL | C1-S | C1E- | C3-S | C6-S | C7s- | C8-S
   4|  0.01|  1.27|  0.00|  0.00||  0.04| 99.96|  3957||  0.00|  0.00|  0.00|  0.00|  1.43|  0.00| 98.52
   1|  0.00| 98.82|  0.00|  0.00||  0.05| 99.95|  3361||  0.00|  0.00|  0.01|  0.00|  0.03|  0.00| 99.88
   5|  0.00| 98.82|  0.00|  0.00||  0.09| 99.91|  3917||  0.00|  0.00|  0.00|  0.00| 99.38|  0.00|  0.50
   2|  0.33|  0.00|  0.00|  0.00||  0.00|100.00|  3890||  0.00|  0.00|  0.00|  0.00|  0.00|  0.00|100.00
   6|  0.33|  0.00|  0.00|  0.00||  0.01| 99.99|  3903||  0.00|  0.00|  0.00|  0.00|  0.00|  0.00| 99.99
   3|  0.01|  0.71|  0.00|  0.00||  0.06| 99.94|  3678||  0.00|  0.00|  0.00|  0.00|  0.80|  0.00| 99.13
   7|  0.01|  0.71|  0.00|  0.00||  0.03| 99.97|  3538||  0.00|  0.69| 11.70|  0.00|  0.00|  0.00| 87.57

There are some minor cleanups included in this patch.

Signed-off-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: Thomas Renninger <trenn@suse.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-07-31 14:17:30 +02:00

180 lines
4.4 KiB
C

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "helpers/helpers.h"
static const char *cpu_vendor_table[X86_VENDOR_MAX] = {
"Unknown", "GenuineIntel", "AuthenticAMD",
};
#if defined(__i386__) || defined(__x86_64__)
/* from gcc */
#include <cpuid.h>
/*
* CPUID functions returning a single datum
*
* Define unsigned int cpuid_e[abcd]x(unsigned int op)
*/
#define cpuid_func(reg) \
unsigned int cpuid_##reg(unsigned int op) \
{ \
unsigned int eax, ebx, ecx, edx; \
__cpuid(op, eax, ebx, ecx, edx); \
return reg; \
}
cpuid_func(eax);
cpuid_func(ebx);
cpuid_func(ecx);
cpuid_func(edx);
#endif /* defined(__i386__) || defined(__x86_64__) */
/* get_cpu_info
*
* Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
*
* Returns 0 on success or a negativ error code
*
* TBD: Should there be a cpuid alternative for this if /proc is not mounted?
*/
int get_cpu_info(struct cpupower_cpu_info *cpu_info)
{
FILE *fp;
char value[64];
unsigned int proc, x;
unsigned int unknown = 0xffffff;
unsigned int cpuid_level, ext_cpuid_level;
int ret = -EINVAL;
cpu_info->vendor = X86_VENDOR_UNKNOWN;
cpu_info->family = unknown;
cpu_info->model = unknown;
cpu_info->stepping = unknown;
cpu_info->caps = 0;
fp = fopen("/proc/cpuinfo", "r");
if (!fp)
return -EIO;
while (!feof(fp)) {
if (!fgets(value, 64, fp))
continue;
value[63 - 1] = '\0';
if (!strncmp(value, "processor\t: ", 12))
sscanf(value, "processor\t: %u", &proc);
if (proc != (unsigned int)base_cpu)
continue;
/* Get CPU vendor */
if (!strncmp(value, "vendor_id", 9)) {
for (x = 1; x < X86_VENDOR_MAX; x++) {
if (strstr(value, cpu_vendor_table[x]))
cpu_info->vendor = x;
}
/* Get CPU family, etc. */
} else if (!strncmp(value, "cpu family\t: ", 13)) {
sscanf(value, "cpu family\t: %u",
&cpu_info->family);
} else if (!strncmp(value, "model\t\t: ", 9)) {
sscanf(value, "model\t\t: %u",
&cpu_info->model);
} else if (!strncmp(value, "stepping\t: ", 10)) {
sscanf(value, "stepping\t: %u",
&cpu_info->stepping);
/* Exit -> all values must have been set */
if (cpu_info->vendor == X86_VENDOR_UNKNOWN ||
cpu_info->family == unknown ||
cpu_info->model == unknown ||
cpu_info->stepping == unknown) {
ret = -EINVAL;
goto out;
}
ret = 0;
goto out;
}
}
ret = -ENODEV;
out:
fclose(fp);
/* Get some useful CPU capabilities from cpuid */
if (cpu_info->vendor != X86_VENDOR_AMD &&
cpu_info->vendor != X86_VENDOR_INTEL)
return ret;
cpuid_level = cpuid_eax(0);
ext_cpuid_level = cpuid_eax(0x80000000);
/* Invariant TSC */
if (ext_cpuid_level >= 0x80000007 &&
(cpuid_edx(0x80000007) & (1 << 8)))
cpu_info->caps |= CPUPOWER_CAP_INV_TSC;
/* Aperf/Mperf registers support */
if (cpuid_level >= 6 && (cpuid_ecx(6) & 0x1))
cpu_info->caps |= CPUPOWER_CAP_APERF;
/* AMD Boost state enable/disable register */
if (cpu_info->vendor == X86_VENDOR_AMD) {
if (ext_cpuid_level >= 0x80000007 &&
(cpuid_edx(0x80000007) & (1 << 9)))
cpu_info->caps |= CPUPOWER_CAP_AMD_CBP;
}
if (cpu_info->vendor == X86_VENDOR_INTEL) {
if (cpuid_level >= 6 &&
(cpuid_eax(6) & (1 << 1)))
cpu_info->caps |= CPUPOWER_CAP_INTEL_IDA;
}
if (cpu_info->vendor == X86_VENDOR_INTEL) {
/* Intel's perf-bias MSR support */
if (cpuid_level >= 6 && (cpuid_ecx(6) & (1 << 3)))
cpu_info->caps |= CPUPOWER_CAP_PERF_BIAS;
/* Intel's Turbo Ratio Limit support */
if (cpu_info->family == 6) {
switch (cpu_info->model) {
case 0x1A: /* Core i7, Xeon 5500 series
* Bloomfield, Gainstown NHM-EP
*/
case 0x1E: /* Core i7 and i5 Processor
* Clarksfield, Lynnfield, Jasper Forest
*/
case 0x1F: /* Core i7 and i5 Processor - Nehalem */
case 0x25: /* Westmere Client
* Clarkdale, Arrandale
*/
case 0x2C: /* Westmere EP - Gulftown */
cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
break;
case 0x2A: /* SNB */
case 0x2D: /* SNB Xeon */
case 0x3A: /* IVB */
case 0x3E: /* IVB Xeon */
cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
cpu_info->caps |= CPUPOWER_CAP_IS_SNB;
break;
case 0x2E: /* Nehalem-EX Xeon - Beckton */
case 0x2F: /* Westmere-EX Xeon - Eagleton */
default:
break;
}
}
}
/* printf("ID: %u - Extid: 0x%x - Caps: 0x%llx\n",
cpuid_level, ext_cpuid_level, cpu_info->caps);
*/
return ret;
}