blob: 96c495a17010db000fb39b0c1864af7543ba163e [file] [log] [blame]
Jordan Crouse7249f792008-03-20 00:11:05 +00001/*
Jordan Crouse7249f792008-03-20 00:11:05 +00002 *
3 * It is derived from the x86info project, which is GPLv2-licensed.
4 *
5 * Copyright (C) 2001-2007 Dave Jones <davej@codemonkey.org.uk>
6 * Copyright (C) 2008 Advanced Micro Devices, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Jordan Crouse7249f792008-03-20 00:11:05 +000016 */
17
18#include "coreinfo.h"
Jordan Crouse7249f792008-03-20 00:11:05 +000019
Julius Wernereab2a292019-03-05 16:55:15 -080020#if CONFIG(MODULE_CPUINFO)
Jordan Crouse646ee3e2008-05-06 21:32:52 +000021#include <arch/rdtsc.h>
Uwe Hermannab5b3e02008-03-31 20:30:18 +000022
Jordan Crouse7249f792008-03-20 00:11:05 +000023#define VENDOR_INTEL 0x756e6547
24#define VENDOR_AMD 0x68747541
25#define VENDOR_CYRIX 0x69727943
26#define VENDOR_IDT 0x746e6543
27#define VENDOR_GEODE 0x646f6547
28#define VENDOR_RISE 0x52697365
29#define VENDOR_RISE2 0x65736952
30#define VENDOR_SIS 0x20536953
31
32/* CPUID 0x00000001 EDX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000033static const char *generic_cap_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000034 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
35 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
36 "pat", "pse36", "psn", "clflsh", NULL, "ds", "acpi", "mmx",
37 "fxsr", "sse", "sse2", "ss", "ht", "tm", NULL, "pbe"
38};
39
Uwe Hermann3a406fe2008-03-20 01:11:28 +000040/* CPUID 0x00000001 ECX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000041static const char *intel_cap_generic_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000042 "sse3", NULL, NULL, "monitor", "ds-cpl", "vmx", NULL, "est",
43 "tm2", "ssse3", "cntx-id", NULL, NULL, "cx16", "xTPR", NULL,
44 NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
45 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
46};
Uwe Hermann3a406fe2008-03-20 01:11:28 +000047
Jordan Crouse7249f792008-03-20 00:11:05 +000048/* CPUID 0x80000001 EDX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000049static const char *intel_cap_extended_edx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000050 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
51 NULL, NULL, NULL, "SYSCALL", NULL, NULL, NULL, NULL,
52 NULL, NULL, NULL, NULL, "xd", NULL, NULL, NULL,
53 NULL, NULL, NULL, NULL, NULL, "em64t", NULL, NULL,
54};
Uwe Hermann3a406fe2008-03-20 01:11:28 +000055
Jordan Crouse7249f792008-03-20 00:11:05 +000056/* CPUID 0x80000001 ECX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000057static const char *intel_cap_extended_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000058 "lahf_lm", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
59 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
60 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
61 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
62};
63
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000064static const char *amd_cap_generic_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000065 "sse3", NULL, NULL, "mwait", NULL, NULL, NULL, NULL,
66 NULL, NULL, NULL, NULL, NULL, "cmpxchg16b", NULL, NULL,
67 NULL, NULL, NULL, NULL, NULL, NULL, NULL, "popcnt",
68 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
69};
70
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000071static const char *amd_cap_extended_edx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000072 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
73 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
74 "pat", "pse36", NULL, "mp", "nx", NULL, "mmxext", "mmx",
75 "fxsr", "ffxsr", "page1gb", "rdtscp",
76 NULL, "lm", "3dnowext", "3dnow"
77}; /* "mp" defined for CPUs prior to AMD family 0xf */
78
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000079static const char *amd_cap_extended_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000080 "lahf/sahf", "CmpLegacy", "svm", "ExtApicSpace",
81 "LockMovCr0", "abm", "sse4a", "misalignsse",
82 "3dnowPref", "osvw", "ibs", NULL, "skinit", "wdt", NULL, NULL,
83 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
84 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
85};
86
Jacob Garber37bec0b2019-06-28 10:10:37 -060087static uint32_t vendor;
Jordan Crouse7249f792008-03-20 00:11:05 +000088static unsigned int cpu_khz;
89
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000090static void decode_flags(WINDOW *win, unsigned long reg, const char **flags,
91 int *row)
Jordan Crouse7249f792008-03-20 00:11:05 +000092{
Jordan Crouse7249f792008-03-20 00:11:05 +000093 int i;
94 int lrow = *row;
95
96 wmove(win, lrow, 2);
97
Uwe Hermann3a406fe2008-03-20 01:11:28 +000098 for (i = 0; i < 32; i++) {
Jordan Crouse7249f792008-03-20 00:11:05 +000099 if (flags[i] == NULL)
100 continue;
101
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000102 if (reg & (1 << i))
Jordan Crouse7249f792008-03-20 00:11:05 +0000103 wprintw(win, "%s ", flags[i]);
104
105 if (i && (i % 16) == 0) {
106 lrow++;
107 wmove(win, lrow, 2);
108 }
109 }
110
111 *row = lrow;
112}
113
Jordan Crouse7249f792008-03-20 00:11:05 +0000114static void get_features(WINDOW *win, int *row)
115{
Jacob Garber37bec0b2019-06-28 10:10:37 -0600116 uint32_t eax, ebx, ecx, edx;
Jordan Crouse7249f792008-03-20 00:11:05 +0000117 int lrow = *row;
118
119 wmove(win, lrow++, 1);
120 wprintw(win, "Features: ");
121
122 docpuid(0x00000001, &eax, &ebx, &ecx, &edx);
123 decode_flags(win, edx, generic_cap_flags, &lrow);
124
125 lrow++;
126
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000127 switch (vendor) {
Jordan Crouse7249f792008-03-20 00:11:05 +0000128 case VENDOR_AMD:
129 wmove(win, lrow++, 1);
130 wprintw(win, "AMD Extended Flags: ");
131 decode_flags(win, ecx, amd_cap_generic_ecx_flags, &lrow);
132 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
133 decode_flags(win, edx, amd_cap_extended_edx_flags, &lrow);
134 decode_flags(win, ecx, amd_cap_extended_ecx_flags, &lrow);
135 break;
Jordan Crouse7249f792008-03-20 00:11:05 +0000136 case VENDOR_INTEL:
137 wmove(win, lrow++, 1);
138 wprintw(win, "Intel Extended Flags: ");
139 decode_flags(win, ecx, intel_cap_generic_ecx_flags, &lrow);
140 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
141 decode_flags(win, edx, intel_cap_extended_edx_flags, &lrow);
142 decode_flags(win, ecx, intel_cap_extended_ecx_flags, &lrow);
143 break;
144 }
145
146 *row = lrow;
147}
148
149static void do_name(WINDOW *win, int row)
150{
Uwe Hermann35845a22008-03-20 20:05:22 +0000151 char name[49], *p;
Jacob Garber37bec0b2019-06-28 10:10:37 -0600152 uint32_t eax, ebx, ecx, edx;
153 int t;
Jordan Crouse7249f792008-03-20 00:11:05 +0000154
155 p = name;
156
Jacob Garber37bec0b2019-06-28 10:10:37 -0600157 for (uint32_t i = 0x80000002; i <= 0x80000004; i++) {
Jordan Crouse7249f792008-03-20 00:11:05 +0000158 docpuid(i, &eax, &ebx, &ecx, &edx);
159
160 if (eax == 0)
161 break;
162
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000163 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000164 *p++ = eax >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000165 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000166 *p++ = ebx >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000167 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000168 *p++ = ecx >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000169 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000170 *p++ = edx >> (8 * t);
171 }
172
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000173 mvwprintw(win, row, 1, "Processor: %s", name);
Jordan Crouse7249f792008-03-20 00:11:05 +0000174}
175
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000176static int cpuinfo_module_redraw(WINDOW *win)
Jordan Crouse7249f792008-03-20 00:11:05 +0000177{
Jacob Garber37bec0b2019-06-28 10:10:37 -0600178 uint32_t eax, ebx, ecx, edx;
Jordan Crouse7249f792008-03-20 00:11:05 +0000179 unsigned int brand;
Uwe Hermann35845a22008-03-20 20:05:22 +0000180 char *vstr;
Jordan Crouse7249f792008-03-20 00:11:05 +0000181 int row = 2;
182
183 print_module_title(win, "CPU Information");
184
185 docpuid(0, NULL, &vendor, NULL, NULL);
186
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000187 switch (vendor) {
188 case VENDOR_INTEL:
Jordan Crouse7249f792008-03-20 00:11:05 +0000189 vstr = "Intel";
190 break;
191 case VENDOR_AMD:
192 vstr = "AMD";
193 break;
194 case VENDOR_CYRIX:
195 vstr = "Cyrix";
196 break;
197 case VENDOR_IDT:
198 vstr = "IDT";
199 break;
200 case VENDOR_GEODE:
201 vstr = "NatSemi Geode";
202 break;
203 case VENDOR_RISE:
204 case VENDOR_RISE2:
205 vstr = "RISE";
206 break;
207 case VENDOR_SIS:
208 vstr = "SiS";
Uwe Hermann35845a22008-03-20 20:05:22 +0000209 break;
210 default:
211 vstr = "Unknown";
212 break;
Jordan Crouse7249f792008-03-20 00:11:05 +0000213 }
214
215 mvwprintw(win, row++, 1, "Vendor: %s", vstr);
216
217 do_name(win, row++);
218
219 docpuid(0x00000001, &eax, &ebx, &ecx, &edx);
220
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000221 mvwprintw(win, row++, 1, "Family: %X", (eax >> 8) & 0x0f);
Jordan Crouse7249f792008-03-20 00:11:05 +0000222 mvwprintw(win, row++, 1, "Model: %X",
223 ((eax >> 4) & 0xf) | ((eax >> 16) & 0xf) << 4);
224
225 mvwprintw(win, row++, 1, "Stepping: %X", eax & 0xf);
226
227 if (vendor == VENDOR_AMD) {
228 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000229 brand = ((ebx >> 9) & 0x1f);
Jordan Crouse7249f792008-03-20 00:11:05 +0000230
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000231 mvwprintw(win, row++, 1, "Brand: %X", brand);
Jordan Crouse7249f792008-03-20 00:11:05 +0000232 }
233
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000234 if (cpu_khz != 0)
Elyes HAOUAS824b4b82020-02-15 09:27:11 +0100235 mvwprintw(win, row++, 1, "CPU Speed: %d MHz", cpu_khz / 1000);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000236 else
Jordan Crouse7249f792008-03-20 00:11:05 +0000237 mvwprintw(win, row++, 1, "CPU Speed: Error");
Jordan Crouse7249f792008-03-20 00:11:05 +0000238
239 row++;
240 get_features(win, &row);
Uwe Hermann35845a22008-03-20 20:05:22 +0000241
242 return 0;
Jordan Crouse7249f792008-03-20 00:11:05 +0000243}
244
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000245static unsigned int getticks(void)
Jordan Crouse7249f792008-03-20 00:11:05 +0000246{
247 unsigned long long start, end;
248
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000249 /* Read the number of ticks during the period. */
Jordan Crouse7249f792008-03-20 00:11:05 +0000250 start = rdtsc();
251 mdelay(100);
252 end = rdtsc();
253
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000254 return (unsigned int)((end - start) / 100);
Jordan Crouse7249f792008-03-20 00:11:05 +0000255}
256
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000257static int cpuinfo_module_init(void)
Jordan Crouse7249f792008-03-20 00:11:05 +0000258{
259 cpu_khz = getticks();
Uwe Hermann35845a22008-03-20 20:05:22 +0000260 return 0;
Jordan Crouse7249f792008-03-20 00:11:05 +0000261}
262
263struct coreinfo_module cpuinfo_module = {
264 .name = "CPU Info",
265 .init = cpuinfo_module_init,
266 .redraw = cpuinfo_module_redraw,
Jordan Crouse7249f792008-03-20 00:11:05 +0000267};
Uwe Hermannab5b3e02008-03-31 20:30:18 +0000268
269#else
270
271struct coreinfo_module cpuinfo_module = {
272};
273
274#endif