~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/power/cpupower/utils/helpers/cpuid.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <stdio.h>
  3 #include <errno.h>
  4 #include <string.h>
  5 #include <unistd.h>
  6 #include <stdlib.h>
  7 
  8 #include "helpers/helpers.h"
  9 
 10 static const char *cpu_vendor_table[X86_VENDOR_MAX] = {
 11         "Unknown", "GenuineIntel", "AuthenticAMD", "HygonGenuine",
 12 };
 13 
 14 #if defined(__i386__) || defined(__x86_64__)
 15 
 16 /* from gcc */
 17 #include <cpuid.h>
 18 
 19 /*
 20  * CPUID functions returning a single datum
 21  *
 22  * Define unsigned int cpuid_e[abcd]x(unsigned int op)
 23  */
 24 #define cpuid_func(reg)                                 \
 25         unsigned int cpuid_##reg(unsigned int op)       \
 26         {                                               \
 27         unsigned int eax, ebx, ecx, edx;                \
 28         __cpuid(op, eax, ebx, ecx, edx);                \
 29         return reg;                                     \
 30         }
 31 cpuid_func(eax);
 32 cpuid_func(ebx);
 33 cpuid_func(ecx);
 34 cpuid_func(edx);
 35 
 36 #endif /* defined(__i386__) || defined(__x86_64__) */
 37 
 38 /* get_cpu_info
 39  *
 40  * Extract CPU vendor, family, model, stepping info from /proc/cpuinfo
 41  *
 42  * Returns 0 on success or a negativ error code
 43  *
 44  * TBD: Should there be a cpuid alternative for this if /proc is not mounted?
 45  */
 46 int get_cpu_info(struct cpupower_cpu_info *cpu_info)
 47 {
 48         FILE *fp;
 49         char value[64];
 50         unsigned int proc, x;
 51         unsigned int unknown = 0xffffff;
 52         unsigned int cpuid_level, ext_cpuid_level;
 53 
 54         int ret = -EINVAL;
 55 
 56         cpu_info->vendor                = X86_VENDOR_UNKNOWN;
 57         cpu_info->family                = unknown;
 58         cpu_info->model                 = unknown;
 59         cpu_info->stepping              = unknown;
 60         cpu_info->caps                  = 0;
 61 
 62         fp = fopen("/proc/cpuinfo", "r");
 63         if (!fp)
 64                 return -EIO;
 65 
 66         while (!feof(fp)) {
 67                 if (!fgets(value, 64, fp))
 68                         continue;
 69                 value[63 - 1] = '\0';
 70 
 71                 if (!strncmp(value, "processor\t: ", 12))
 72                         sscanf(value, "processor\t: %u", &proc);
 73 
 74                 if (proc != (unsigned int)base_cpu)
 75                         continue;
 76 
 77                 /* Get CPU vendor */
 78                 if (!strncmp(value, "vendor_id", 9)) {
 79                         for (x = 1; x < X86_VENDOR_MAX; x++) {
 80                                 if (strstr(value, cpu_vendor_table[x]))
 81                                         cpu_info->vendor = x;
 82                         }
 83                 /* Get CPU family, etc. */
 84                 } else if (!strncmp(value, "cpu family\t: ", 13)) {
 85                         sscanf(value, "cpu family\t: %u",
 86                                &cpu_info->family);
 87                 } else if (!strncmp(value, "model\t\t: ", 9)) {
 88                         sscanf(value, "model\t\t: %u",
 89                                &cpu_info->model);
 90                 } else if (!strncmp(value, "stepping\t: ", 10)) {
 91                         sscanf(value, "stepping\t: %u",
 92                                &cpu_info->stepping);
 93 
 94                         /* Exit -> all values must have been set */
 95                         if (cpu_info->vendor == X86_VENDOR_UNKNOWN ||
 96                             cpu_info->family == unknown ||
 97                             cpu_info->model == unknown ||
 98                             cpu_info->stepping == unknown) {
 99                                 ret = -EINVAL;
100                                 goto out;
101                         }
102 
103                         ret = 0;
104                         goto out;
105                 }
106         }
107         ret = -ENODEV;
108 out:
109         fclose(fp);
110         /* Get some useful CPU capabilities from cpuid */
111         if (cpu_info->vendor != X86_VENDOR_AMD &&
112             cpu_info->vendor != X86_VENDOR_HYGON &&
113             cpu_info->vendor != X86_VENDOR_INTEL)
114                 return ret;
115 
116         cpuid_level     = cpuid_eax(0);
117         ext_cpuid_level = cpuid_eax(0x80000000);
118 
119         /* Invariant TSC */
120         if (ext_cpuid_level >= 0x80000007 &&
121             (cpuid_edx(0x80000007) & (1 << 8)))
122                 cpu_info->caps |= CPUPOWER_CAP_INV_TSC;
123 
124         /* Aperf/Mperf registers support */
125         if (cpuid_level >= 6 && (cpuid_ecx(6) & 0x1))
126                 cpu_info->caps |= CPUPOWER_CAP_APERF;
127 
128         /* AMD or Hygon Boost state enable/disable register */
129         if (cpu_info->vendor == X86_VENDOR_AMD ||
130             cpu_info->vendor == X86_VENDOR_HYGON) {
131                 if (ext_cpuid_level >= 0x80000007) {
132                         if (cpuid_edx(0x80000007) & (1 << 9)) {
133                                 cpu_info->caps |= CPUPOWER_CAP_AMD_CPB;
134 
135                                 if (cpu_info->family >= 0x17)
136                                         cpu_info->caps |= CPUPOWER_CAP_AMD_CPB_MSR;
137                         }
138 
139                         if ((cpuid_edx(0x80000007) & (1 << 7)) &&
140                             cpu_info->family != 0x14) {
141                                 /* HW pstate was not implemented in family 0x14 */
142                                 cpu_info->caps |= CPUPOWER_CAP_AMD_HW_PSTATE;
143 
144                                 if (cpu_info->family >= 0x17)
145                                         cpu_info->caps |= CPUPOWER_CAP_AMD_PSTATEDEF;
146                         }
147                 }
148 
149                 if (ext_cpuid_level >= 0x80000008 &&
150                     cpuid_ebx(0x80000008) & (1 << 4))
151                         cpu_info->caps |= CPUPOWER_CAP_AMD_RDPRU;
152 
153                 if (cpupower_amd_pstate_enabled()) {
154                         cpu_info->caps |= CPUPOWER_CAP_AMD_PSTATE;
155 
156                         /*
157                          * If AMD P-State is enabled, the firmware will treat
158                          * AMD P-State function as high priority.
159                          */
160                         cpu_info->caps &= ~CPUPOWER_CAP_AMD_CPB;
161                         cpu_info->caps &= ~CPUPOWER_CAP_AMD_CPB_MSR;
162                         cpu_info->caps &= ~CPUPOWER_CAP_AMD_HW_PSTATE;
163                         cpu_info->caps &= ~CPUPOWER_CAP_AMD_PSTATEDEF;
164                 }
165         }
166 
167         if (cpu_info->vendor == X86_VENDOR_INTEL) {
168                 if (cpuid_level >= 6 &&
169                     (cpuid_eax(6) & (1 << 1)))
170                         cpu_info->caps |= CPUPOWER_CAP_INTEL_IDA;
171         }
172 
173         if (cpu_info->vendor == X86_VENDOR_INTEL) {
174                 /* Intel's perf-bias MSR support */
175                 if (cpuid_level >= 6 && (cpuid_ecx(6) & (1 << 3)))
176                         cpu_info->caps |= CPUPOWER_CAP_PERF_BIAS;
177 
178                 /* Intel's Turbo Ratio Limit support */
179                 if (cpu_info->family == 6) {
180                         switch (cpu_info->model) {
181                         case 0x1A:      /* Core i7, Xeon 5500 series
182                                          * Bloomfield, Gainstown NHM-EP
183                                          */
184                         case 0x1E:      /* Core i7 and i5 Processor
185                                          * Clarksfield, Lynnfield, Jasper Forest
186                                          */
187                         case 0x1F:      /* Core i7 and i5 Processor - Nehalem */
188                         case 0x25:      /* Westmere Client
189                                          * Clarkdale, Arrandale
190                                          */
191                         case 0x2C:      /* Westmere EP - Gulftown */
192                                 cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
193                                 break;
194                         case 0x2A:      /* SNB */
195                         case 0x2D:      /* SNB Xeon */
196                         case 0x3A:      /* IVB */
197                         case 0x3E:      /* IVB Xeon */
198                                 cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
199                                 cpu_info->caps |= CPUPOWER_CAP_IS_SNB;
200                                 break;
201                         case 0x2E:      /* Nehalem-EX Xeon - Beckton */
202                         case 0x2F:      /* Westmere-EX Xeon - Eagleton */
203                         default:
204                                 break;
205                         }
206                 }
207         }
208 
209         /*      printf("ID: %u - Extid: 0x%x - Caps: 0x%llx\n",
210                 cpuid_level, ext_cpuid_level, cpu_info->caps);
211         */
212         return ret;
213 }
214 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php