blob: 8548a250692aed3b3fdf39ed68daa2d074267872 [file] [log] [blame]
Jordan Crouse7249f792008-03-20 00:11:05 +00001/*
2 * This file is part of the coreinfo project.
3 *
4 * It is derived from the x86info project, which is GPLv2-licensed.
5 *
6 * Copyright (C) 2001-2007 Dave Jones <davej@codemonkey.org.uk>
7 * Copyright (C) 2008 Advanced Micro Devices, Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include "coreinfo.h"
24#include <arch/rdtsc.h>
25
Uwe Hermannab5b3e02008-03-31 20:30:18 +000026#ifdef CONFIG_MODULE_CPUINFO
27
Jordan Crouse7249f792008-03-20 00:11:05 +000028#define VENDOR_INTEL 0x756e6547
29#define VENDOR_AMD 0x68747541
30#define VENDOR_CYRIX 0x69727943
31#define VENDOR_IDT 0x746e6543
32#define VENDOR_GEODE 0x646f6547
33#define VENDOR_RISE 0x52697365
34#define VENDOR_RISE2 0x65736952
35#define VENDOR_SIS 0x20536953
36
37/* CPUID 0x00000001 EDX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000038static const char *generic_cap_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000039 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
40 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
41 "pat", "pse36", "psn", "clflsh", NULL, "ds", "acpi", "mmx",
42 "fxsr", "sse", "sse2", "ss", "ht", "tm", NULL, "pbe"
43};
44
Uwe Hermann3a406fe2008-03-20 01:11:28 +000045/* CPUID 0x00000001 ECX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000046static const char *intel_cap_generic_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000047 "sse3", NULL, NULL, "monitor", "ds-cpl", "vmx", NULL, "est",
48 "tm2", "ssse3", "cntx-id", NULL, NULL, "cx16", "xTPR", NULL,
49 NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
50 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
51};
Uwe Hermann3a406fe2008-03-20 01:11:28 +000052
Jordan Crouse7249f792008-03-20 00:11:05 +000053/* CPUID 0x80000001 EDX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000054static const char *intel_cap_extended_edx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000055 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
56 NULL, NULL, NULL, "SYSCALL", NULL, NULL, NULL, NULL,
57 NULL, NULL, NULL, NULL, "xd", NULL, NULL, NULL,
58 NULL, NULL, NULL, NULL, NULL, "em64t", NULL, NULL,
59};
Uwe Hermann3a406fe2008-03-20 01:11:28 +000060
Jordan Crouse7249f792008-03-20 00:11:05 +000061/* CPUID 0x80000001 ECX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000062static const char *intel_cap_extended_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000063 "lahf_lm", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
64 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
65 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
66 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
67};
68
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000069static const char *amd_cap_generic_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000070 "sse3", NULL, NULL, "mwait", NULL, NULL, NULL, NULL,
71 NULL, NULL, NULL, NULL, NULL, "cmpxchg16b", NULL, NULL,
72 NULL, NULL, NULL, NULL, NULL, NULL, NULL, "popcnt",
73 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
74};
75
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000076static const char *amd_cap_extended_edx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000077 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
78 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
79 "pat", "pse36", NULL, "mp", "nx", NULL, "mmxext", "mmx",
80 "fxsr", "ffxsr", "page1gb", "rdtscp",
81 NULL, "lm", "3dnowext", "3dnow"
82}; /* "mp" defined for CPUs prior to AMD family 0xf */
83
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000084static const char *amd_cap_extended_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000085 "lahf/sahf", "CmpLegacy", "svm", "ExtApicSpace",
86 "LockMovCr0", "abm", "sse4a", "misalignsse",
87 "3dnowPref", "osvw", "ibs", NULL, "skinit", "wdt", NULL, NULL,
88 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
89 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
90};
91
92static unsigned long vendor;
93static unsigned int cpu_khz;
94
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000095static void decode_flags(WINDOW *win, unsigned long reg, const char **flags,
96 int *row)
Jordan Crouse7249f792008-03-20 00:11:05 +000097{
Jordan Crouse7249f792008-03-20 00:11:05 +000098 int i;
99 int lrow = *row;
100
101 wmove(win, lrow, 2);
102
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000103 for (i = 0; i < 32; i++) {
Jordan Crouse7249f792008-03-20 00:11:05 +0000104 if (flags[i] == NULL)
105 continue;
106
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000107 if (reg & (1 << i))
Jordan Crouse7249f792008-03-20 00:11:05 +0000108 wprintw(win, "%s ", flags[i]);
109
110 if (i && (i % 16) == 0) {
111 lrow++;
112 wmove(win, lrow, 2);
113 }
114 }
115
116 *row = lrow;
117}
118
Jordan Crouse7249f792008-03-20 00:11:05 +0000119static void get_features(WINDOW *win, int *row)
120{
121 unsigned long eax, ebx, ecx, edx;
Jordan Crouse7249f792008-03-20 00:11:05 +0000122 int lrow = *row;
123
124 wmove(win, lrow++, 1);
125 wprintw(win, "Features: ");
126
127 docpuid(0x00000001, &eax, &ebx, &ecx, &edx);
128 decode_flags(win, edx, generic_cap_flags, &lrow);
129
130 lrow++;
131
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000132 switch (vendor) {
Jordan Crouse7249f792008-03-20 00:11:05 +0000133 case VENDOR_AMD:
134 wmove(win, lrow++, 1);
135 wprintw(win, "AMD Extended Flags: ");
136 decode_flags(win, ecx, amd_cap_generic_ecx_flags, &lrow);
137 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
138 decode_flags(win, edx, amd_cap_extended_edx_flags, &lrow);
139 decode_flags(win, ecx, amd_cap_extended_ecx_flags, &lrow);
140 break;
Jordan Crouse7249f792008-03-20 00:11:05 +0000141 case VENDOR_INTEL:
142 wmove(win, lrow++, 1);
143 wprintw(win, "Intel Extended Flags: ");
144 decode_flags(win, ecx, intel_cap_generic_ecx_flags, &lrow);
145 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
146 decode_flags(win, edx, intel_cap_extended_edx_flags, &lrow);
147 decode_flags(win, ecx, intel_cap_extended_ecx_flags, &lrow);
148 break;
149 }
150
151 *row = lrow;
152}
153
154static void do_name(WINDOW *win, int row)
155{
Uwe Hermann35845a22008-03-20 20:05:22 +0000156 char name[49], *p;
Jordan Crouse7249f792008-03-20 00:11:05 +0000157 unsigned long eax, ebx, ecx, edx;
158 int i, t;
Jordan Crouse7249f792008-03-20 00:11:05 +0000159
160 p = name;
161
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000162 for (i = 0x80000002; i <= 0x80000004; i++) {
Jordan Crouse7249f792008-03-20 00:11:05 +0000163 docpuid(i, &eax, &ebx, &ecx, &edx);
164
165 if (eax == 0)
166 break;
167
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000168 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000169 *p++ = eax >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000170 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000171 *p++ = ebx >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000172 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000173 *p++ = ecx >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000174 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000175 *p++ = edx >> (8 * t);
176 }
177
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000178 mvwprintw(win, row, 1, "Processor: %s", name);
Jordan Crouse7249f792008-03-20 00:11:05 +0000179}
180
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000181static int cpuinfo_module_redraw(WINDOW *win)
Jordan Crouse7249f792008-03-20 00:11:05 +0000182{
183 unsigned long eax, ebx, ecx, edx;
Jordan Crouse7249f792008-03-20 00:11:05 +0000184 unsigned int brand;
Uwe Hermann35845a22008-03-20 20:05:22 +0000185 char *vstr;
Jordan Crouse7249f792008-03-20 00:11:05 +0000186 int row = 2;
187
188 print_module_title(win, "CPU Information");
189
190 docpuid(0, NULL, &vendor, NULL, NULL);
191
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000192 switch (vendor) {
193 case VENDOR_INTEL:
Jordan Crouse7249f792008-03-20 00:11:05 +0000194 vstr = "Intel";
195 break;
196 case VENDOR_AMD:
197 vstr = "AMD";
198 break;
199 case VENDOR_CYRIX:
200 vstr = "Cyrix";
201 break;
202 case VENDOR_IDT:
203 vstr = "IDT";
204 break;
205 case VENDOR_GEODE:
206 vstr = "NatSemi Geode";
207 break;
208 case VENDOR_RISE:
209 case VENDOR_RISE2:
210 vstr = "RISE";
211 break;
212 case VENDOR_SIS:
213 vstr = "SiS";
Uwe Hermann35845a22008-03-20 20:05:22 +0000214 break;
215 default:
216 vstr = "Unknown";
217 break;
Jordan Crouse7249f792008-03-20 00:11:05 +0000218 }
219
220 mvwprintw(win, row++, 1, "Vendor: %s", vstr);
221
222 do_name(win, row++);
223
224 docpuid(0x00000001, &eax, &ebx, &ecx, &edx);
225
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000226 mvwprintw(win, row++, 1, "Family: %X", (eax >> 8) & 0x0f);
Jordan Crouse7249f792008-03-20 00:11:05 +0000227 mvwprintw(win, row++, 1, "Model: %X",
228 ((eax >> 4) & 0xf) | ((eax >> 16) & 0xf) << 4);
229
230 mvwprintw(win, row++, 1, "Stepping: %X", eax & 0xf);
231
232 if (vendor == VENDOR_AMD) {
233 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000234 brand = ((ebx >> 9) & 0x1f);
Jordan Crouse7249f792008-03-20 00:11:05 +0000235
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000236 mvwprintw(win, row++, 1, "Brand: %X", brand);
Jordan Crouse7249f792008-03-20 00:11:05 +0000237 }
238
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000239 if (cpu_khz != 0)
240 mvwprintw(win, row++, 1, "CPU Speed: %d Mhz", cpu_khz / 1000);
241 else
Jordan Crouse7249f792008-03-20 00:11:05 +0000242 mvwprintw(win, row++, 1, "CPU Speed: Error");
Jordan Crouse7249f792008-03-20 00:11:05 +0000243
244 row++;
245 get_features(win, &row);
Uwe Hermann35845a22008-03-20 20:05:22 +0000246
247 return 0;
Jordan Crouse7249f792008-03-20 00:11:05 +0000248}
249
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000250static unsigned int getticks(void)
Jordan Crouse7249f792008-03-20 00:11:05 +0000251{
252 unsigned long long start, end;
253
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000254 /* Read the number of ticks during the period. */
Jordan Crouse7249f792008-03-20 00:11:05 +0000255 start = rdtsc();
256 mdelay(100);
257 end = rdtsc();
258
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000259 return (unsigned int)((end - start) / 100);
Jordan Crouse7249f792008-03-20 00:11:05 +0000260}
261
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000262static int cpuinfo_module_init(void)
Jordan Crouse7249f792008-03-20 00:11:05 +0000263{
264 cpu_khz = getticks();
Uwe Hermann35845a22008-03-20 20:05:22 +0000265 return 0;
Jordan Crouse7249f792008-03-20 00:11:05 +0000266}
267
268struct coreinfo_module cpuinfo_module = {
269 .name = "CPU Info",
270 .init = cpuinfo_module_init,
271 .redraw = cpuinfo_module_redraw,
Jordan Crouse7249f792008-03-20 00:11:05 +0000272};
Uwe Hermannab5b3e02008-03-31 20:30:18 +0000273
274#else
275
276struct coreinfo_module cpuinfo_module = {
277};
278
279#endif