blob: b937e4c1d4e1d226f48fbe7f537f603d47ef7e48 [file] [log] [blame]
Jacob Garber07201d72020-09-08 12:25:44 -06001/* SPDX-License-Identifier: GPL-2.0-only */
2
3/* It is derived from the x86info project, which is GPLv2-licensed. */
Jordan Crouse7249f792008-03-20 00:11:05 +00004
5#include "coreinfo.h"
Jordan Crouse7249f792008-03-20 00:11:05 +00006
Julius Wernereab2a292019-03-05 16:55:15 -08007#if CONFIG(MODULE_CPUINFO)
Jordan Crouse646ee3e2008-05-06 21:32:52 +00008#include <arch/rdtsc.h>
Uwe Hermannab5b3e02008-03-31 20:30:18 +00009
Jordan Crouse7249f792008-03-20 00:11:05 +000010#define VENDOR_INTEL 0x756e6547
11#define VENDOR_AMD 0x68747541
12#define VENDOR_CYRIX 0x69727943
13#define VENDOR_IDT 0x746e6543
14#define VENDOR_GEODE 0x646f6547
15#define VENDOR_RISE 0x52697365
16#define VENDOR_RISE2 0x65736952
17#define VENDOR_SIS 0x20536953
18
19/* CPUID 0x00000001 EDX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000020static const char *generic_cap_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000021 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
22 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
23 "pat", "pse36", "psn", "clflsh", NULL, "ds", "acpi", "mmx",
24 "fxsr", "sse", "sse2", "ss", "ht", "tm", NULL, "pbe"
25};
26
Uwe Hermann3a406fe2008-03-20 01:11:28 +000027/* CPUID 0x00000001 ECX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000028static const char *intel_cap_generic_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000029 "sse3", NULL, NULL, "monitor", "ds-cpl", "vmx", NULL, "est",
30 "tm2", "ssse3", "cntx-id", NULL, NULL, "cx16", "xTPR", NULL,
31 NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
32 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
33};
Uwe Hermann3a406fe2008-03-20 01:11:28 +000034
Jordan Crouse7249f792008-03-20 00:11:05 +000035/* CPUID 0x80000001 EDX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000036static const char *intel_cap_extended_edx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000037 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
38 NULL, NULL, NULL, "SYSCALL", NULL, NULL, NULL, NULL,
39 NULL, NULL, NULL, NULL, "xd", NULL, NULL, NULL,
40 NULL, NULL, NULL, NULL, NULL, "em64t", NULL, NULL,
41};
Uwe Hermann3a406fe2008-03-20 01:11:28 +000042
Jordan Crouse7249f792008-03-20 00:11:05 +000043/* CPUID 0x80000001 ECX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000044static const char *intel_cap_extended_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000045 "lahf_lm", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
46 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
47 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
48 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
49};
50
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000051static const char *amd_cap_generic_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000052 "sse3", NULL, NULL, "mwait", NULL, NULL, NULL, NULL,
53 NULL, NULL, NULL, NULL, NULL, "cmpxchg16b", NULL, NULL,
54 NULL, NULL, NULL, NULL, NULL, NULL, NULL, "popcnt",
55 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
56};
57
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000058static const char *amd_cap_extended_edx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000059 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
60 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
61 "pat", "pse36", NULL, "mp", "nx", NULL, "mmxext", "mmx",
62 "fxsr", "ffxsr", "page1gb", "rdtscp",
63 NULL, "lm", "3dnowext", "3dnow"
64}; /* "mp" defined for CPUs prior to AMD family 0xf */
65
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000066static const char *amd_cap_extended_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000067 "lahf/sahf", "CmpLegacy", "svm", "ExtApicSpace",
68 "LockMovCr0", "abm", "sse4a", "misalignsse",
69 "3dnowPref", "osvw", "ibs", NULL, "skinit", "wdt", NULL, NULL,
70 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
71 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
72};
73
Jacob Garber37bec0b2019-06-28 10:10:37 -060074static uint32_t vendor;
Jordan Crouse7249f792008-03-20 00:11:05 +000075static unsigned int cpu_khz;
76
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000077static void decode_flags(WINDOW *win, unsigned long reg, const char **flags,
78 int *row)
Jordan Crouse7249f792008-03-20 00:11:05 +000079{
Jordan Crouse7249f792008-03-20 00:11:05 +000080 int i;
81 int lrow = *row;
82
83 wmove(win, lrow, 2);
84
Uwe Hermann3a406fe2008-03-20 01:11:28 +000085 for (i = 0; i < 32; i++) {
Jordan Crouse7249f792008-03-20 00:11:05 +000086 if (flags[i] == NULL)
87 continue;
88
Uwe Hermann3a406fe2008-03-20 01:11:28 +000089 if (reg & (1 << i))
Jordan Crouse7249f792008-03-20 00:11:05 +000090 wprintw(win, "%s ", flags[i]);
91
92 if (i && (i % 16) == 0) {
93 lrow++;
94 wmove(win, lrow, 2);
95 }
96 }
97
98 *row = lrow;
99}
100
Jordan Crouse7249f792008-03-20 00:11:05 +0000101static void get_features(WINDOW *win, int *row)
102{
Jacob Garber37bec0b2019-06-28 10:10:37 -0600103 uint32_t eax, ebx, ecx, edx;
Jordan Crouse7249f792008-03-20 00:11:05 +0000104 int lrow = *row;
105
106 wmove(win, lrow++, 1);
107 wprintw(win, "Features: ");
108
109 docpuid(0x00000001, &eax, &ebx, &ecx, &edx);
110 decode_flags(win, edx, generic_cap_flags, &lrow);
111
112 lrow++;
113
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000114 switch (vendor) {
Jordan Crouse7249f792008-03-20 00:11:05 +0000115 case VENDOR_AMD:
116 wmove(win, lrow++, 1);
117 wprintw(win, "AMD Extended Flags: ");
118 decode_flags(win, ecx, amd_cap_generic_ecx_flags, &lrow);
119 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
120 decode_flags(win, edx, amd_cap_extended_edx_flags, &lrow);
121 decode_flags(win, ecx, amd_cap_extended_ecx_flags, &lrow);
122 break;
Jordan Crouse7249f792008-03-20 00:11:05 +0000123 case VENDOR_INTEL:
124 wmove(win, lrow++, 1);
125 wprintw(win, "Intel Extended Flags: ");
126 decode_flags(win, ecx, intel_cap_generic_ecx_flags, &lrow);
127 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
128 decode_flags(win, edx, intel_cap_extended_edx_flags, &lrow);
129 decode_flags(win, ecx, intel_cap_extended_ecx_flags, &lrow);
130 break;
131 }
132
133 *row = lrow;
134}
135
136static void do_name(WINDOW *win, int row)
137{
Uwe Hermann35845a22008-03-20 20:05:22 +0000138 char name[49], *p;
Jacob Garber37bec0b2019-06-28 10:10:37 -0600139 uint32_t eax, ebx, ecx, edx;
140 int t;
Jordan Crouse7249f792008-03-20 00:11:05 +0000141
142 p = name;
143
Jacob Garber37bec0b2019-06-28 10:10:37 -0600144 for (uint32_t i = 0x80000002; i <= 0x80000004; i++) {
Jordan Crouse7249f792008-03-20 00:11:05 +0000145 docpuid(i, &eax, &ebx, &ecx, &edx);
146
147 if (eax == 0)
148 break;
149
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000150 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000151 *p++ = eax >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000152 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000153 *p++ = ebx >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000154 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000155 *p++ = ecx >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000156 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000157 *p++ = edx >> (8 * t);
158 }
159
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000160 mvwprintw(win, row, 1, "Processor: %s", name);
Jordan Crouse7249f792008-03-20 00:11:05 +0000161}
162
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000163static int cpuinfo_module_redraw(WINDOW *win)
Jordan Crouse7249f792008-03-20 00:11:05 +0000164{
Jacob Garber37bec0b2019-06-28 10:10:37 -0600165 uint32_t eax, ebx, ecx, edx;
Jordan Crouse7249f792008-03-20 00:11:05 +0000166 unsigned int brand;
Uwe Hermann35845a22008-03-20 20:05:22 +0000167 char *vstr;
Jordan Crouse7249f792008-03-20 00:11:05 +0000168 int row = 2;
169
170 print_module_title(win, "CPU Information");
171
172 docpuid(0, NULL, &vendor, NULL, NULL);
173
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000174 switch (vendor) {
175 case VENDOR_INTEL:
Jordan Crouse7249f792008-03-20 00:11:05 +0000176 vstr = "Intel";
177 break;
178 case VENDOR_AMD:
179 vstr = "AMD";
180 break;
181 case VENDOR_CYRIX:
182 vstr = "Cyrix";
183 break;
184 case VENDOR_IDT:
185 vstr = "IDT";
186 break;
187 case VENDOR_GEODE:
188 vstr = "NatSemi Geode";
189 break;
190 case VENDOR_RISE:
191 case VENDOR_RISE2:
192 vstr = "RISE";
193 break;
194 case VENDOR_SIS:
195 vstr = "SiS";
Uwe Hermann35845a22008-03-20 20:05:22 +0000196 break;
197 default:
198 vstr = "Unknown";
199 break;
Jordan Crouse7249f792008-03-20 00:11:05 +0000200 }
201
202 mvwprintw(win, row++, 1, "Vendor: %s", vstr);
203
204 do_name(win, row++);
205
206 docpuid(0x00000001, &eax, &ebx, &ecx, &edx);
207
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000208 mvwprintw(win, row++, 1, "Family: %X", (eax >> 8) & 0x0f);
Jordan Crouse7249f792008-03-20 00:11:05 +0000209 mvwprintw(win, row++, 1, "Model: %X",
210 ((eax >> 4) & 0xf) | ((eax >> 16) & 0xf) << 4);
211
212 mvwprintw(win, row++, 1, "Stepping: %X", eax & 0xf);
213
214 if (vendor == VENDOR_AMD) {
215 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000216 brand = ((ebx >> 9) & 0x1f);
Jordan Crouse7249f792008-03-20 00:11:05 +0000217
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000218 mvwprintw(win, row++, 1, "Brand: %X", brand);
Jordan Crouse7249f792008-03-20 00:11:05 +0000219 }
220
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000221 if (cpu_khz != 0)
Elyes HAOUAS824b4b82020-02-15 09:27:11 +0100222 mvwprintw(win, row++, 1, "CPU Speed: %d MHz", cpu_khz / 1000);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000223 else
Jordan Crouse7249f792008-03-20 00:11:05 +0000224 mvwprintw(win, row++, 1, "CPU Speed: Error");
Jordan Crouse7249f792008-03-20 00:11:05 +0000225
226 row++;
227 get_features(win, &row);
Uwe Hermann35845a22008-03-20 20:05:22 +0000228
229 return 0;
Jordan Crouse7249f792008-03-20 00:11:05 +0000230}
231
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000232static unsigned int getticks(void)
Jordan Crouse7249f792008-03-20 00:11:05 +0000233{
234 unsigned long long start, end;
235
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000236 /* Read the number of ticks during the period. */
Jordan Crouse7249f792008-03-20 00:11:05 +0000237 start = rdtsc();
238 mdelay(100);
239 end = rdtsc();
240
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000241 return (unsigned int)((end - start) / 100);
Jordan Crouse7249f792008-03-20 00:11:05 +0000242}
243
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000244static int cpuinfo_module_init(void)
Jordan Crouse7249f792008-03-20 00:11:05 +0000245{
246 cpu_khz = getticks();
Uwe Hermann35845a22008-03-20 20:05:22 +0000247 return 0;
Jordan Crouse7249f792008-03-20 00:11:05 +0000248}
249
250struct coreinfo_module cpuinfo_module = {
251 .name = "CPU Info",
252 .init = cpuinfo_module_init,
253 .redraw = cpuinfo_module_redraw,
Jordan Crouse7249f792008-03-20 00:11:05 +0000254};
Uwe Hermannab5b3e02008-03-31 20:30:18 +0000255
256#else
257
258struct coreinfo_module cpuinfo_module = {
259};
260
261#endif