blob: 72b941ef277aa006a867689ea6e45957d2333a05 [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.
Jordan Crouse7249f792008-03-20 00:11:05 +000017 */
18
19#include "coreinfo.h"
Jordan Crouse7249f792008-03-20 00:11:05 +000020
Stefan Reinauer04fb7a82015-06-29 16:08:39 -070021#if IS_ENABLED(CONFIG_MODULE_CPUINFO)
Jordan Crouse646ee3e2008-05-06 21:32:52 +000022#include <arch/rdtsc.h>
Uwe Hermannab5b3e02008-03-31 20:30:18 +000023
Jordan Crouse7249f792008-03-20 00:11:05 +000024#define VENDOR_INTEL 0x756e6547
25#define VENDOR_AMD 0x68747541
26#define VENDOR_CYRIX 0x69727943
27#define VENDOR_IDT 0x746e6543
28#define VENDOR_GEODE 0x646f6547
29#define VENDOR_RISE 0x52697365
30#define VENDOR_RISE2 0x65736952
31#define VENDOR_SIS 0x20536953
32
33/* CPUID 0x00000001 EDX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000034static const char *generic_cap_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000035 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
36 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
37 "pat", "pse36", "psn", "clflsh", NULL, "ds", "acpi", "mmx",
38 "fxsr", "sse", "sse2", "ss", "ht", "tm", NULL, "pbe"
39};
40
Uwe Hermann3a406fe2008-03-20 01:11:28 +000041/* CPUID 0x00000001 ECX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000042static const char *intel_cap_generic_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000043 "sse3", NULL, NULL, "monitor", "ds-cpl", "vmx", NULL, "est",
44 "tm2", "ssse3", "cntx-id", NULL, NULL, "cx16", "xTPR", NULL,
45 NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
46 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
47};
Uwe Hermann3a406fe2008-03-20 01:11:28 +000048
Jordan Crouse7249f792008-03-20 00:11:05 +000049/* CPUID 0x80000001 EDX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000050static const char *intel_cap_extended_edx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000051 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
52 NULL, NULL, NULL, "SYSCALL", NULL, NULL, NULL, NULL,
53 NULL, NULL, NULL, NULL, "xd", NULL, NULL, NULL,
54 NULL, NULL, NULL, NULL, NULL, "em64t", NULL, NULL,
55};
Uwe Hermann3a406fe2008-03-20 01:11:28 +000056
Jordan Crouse7249f792008-03-20 00:11:05 +000057/* CPUID 0x80000001 ECX flags */
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000058static const char *intel_cap_extended_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000059 "lahf_lm", 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 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
63};
64
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000065static const char *amd_cap_generic_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000066 "sse3", NULL, NULL, "mwait", NULL, NULL, NULL, NULL,
67 NULL, NULL, NULL, NULL, NULL, "cmpxchg16b", NULL, NULL,
68 NULL, NULL, NULL, NULL, NULL, NULL, NULL, "popcnt",
69 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
70};
71
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000072static const char *amd_cap_extended_edx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000073 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
74 "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
75 "pat", "pse36", NULL, "mp", "nx", NULL, "mmxext", "mmx",
76 "fxsr", "ffxsr", "page1gb", "rdtscp",
77 NULL, "lm", "3dnowext", "3dnow"
78}; /* "mp" defined for CPUs prior to AMD family 0xf */
79
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000080static const char *amd_cap_extended_ecx_flags[] = {
Jordan Crouse7249f792008-03-20 00:11:05 +000081 "lahf/sahf", "CmpLegacy", "svm", "ExtApicSpace",
82 "LockMovCr0", "abm", "sse4a", "misalignsse",
83 "3dnowPref", "osvw", "ibs", NULL, "skinit", "wdt", NULL, NULL,
84 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
85 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
86};
87
88static unsigned long vendor;
89static unsigned int cpu_khz;
90
Uwe Hermann0bfb5c42008-03-23 15:34:04 +000091static void decode_flags(WINDOW *win, unsigned long reg, const char **flags,
92 int *row)
Jordan Crouse7249f792008-03-20 00:11:05 +000093{
Jordan Crouse7249f792008-03-20 00:11:05 +000094 int i;
95 int lrow = *row;
96
97 wmove(win, lrow, 2);
98
Uwe Hermann3a406fe2008-03-20 01:11:28 +000099 for (i = 0; i < 32; i++) {
Jordan Crouse7249f792008-03-20 00:11:05 +0000100 if (flags[i] == NULL)
101 continue;
102
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000103 if (reg & (1 << i))
Jordan Crouse7249f792008-03-20 00:11:05 +0000104 wprintw(win, "%s ", flags[i]);
105
106 if (i && (i % 16) == 0) {
107 lrow++;
108 wmove(win, lrow, 2);
109 }
110 }
111
112 *row = lrow;
113}
114
Jordan Crouse7249f792008-03-20 00:11:05 +0000115static void get_features(WINDOW *win, int *row)
116{
117 unsigned long eax, ebx, ecx, edx;
Jordan Crouse7249f792008-03-20 00:11:05 +0000118 int lrow = *row;
119
120 wmove(win, lrow++, 1);
121 wprintw(win, "Features: ");
122
123 docpuid(0x00000001, &eax, &ebx, &ecx, &edx);
124 decode_flags(win, edx, generic_cap_flags, &lrow);
125
126 lrow++;
127
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000128 switch (vendor) {
Jordan Crouse7249f792008-03-20 00:11:05 +0000129 case VENDOR_AMD:
130 wmove(win, lrow++, 1);
131 wprintw(win, "AMD Extended Flags: ");
132 decode_flags(win, ecx, amd_cap_generic_ecx_flags, &lrow);
133 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
134 decode_flags(win, edx, amd_cap_extended_edx_flags, &lrow);
135 decode_flags(win, ecx, amd_cap_extended_ecx_flags, &lrow);
136 break;
Jordan Crouse7249f792008-03-20 00:11:05 +0000137 case VENDOR_INTEL:
138 wmove(win, lrow++, 1);
139 wprintw(win, "Intel Extended Flags: ");
140 decode_flags(win, ecx, intel_cap_generic_ecx_flags, &lrow);
141 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
142 decode_flags(win, edx, intel_cap_extended_edx_flags, &lrow);
143 decode_flags(win, ecx, intel_cap_extended_ecx_flags, &lrow);
144 break;
145 }
146
147 *row = lrow;
148}
149
150static void do_name(WINDOW *win, int row)
151{
Uwe Hermann35845a22008-03-20 20:05:22 +0000152 char name[49], *p;
Jordan Crouse7249f792008-03-20 00:11:05 +0000153 unsigned long eax, ebx, ecx, edx;
154 int i, t;
Jordan Crouse7249f792008-03-20 00:11:05 +0000155
156 p = name;
157
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000158 for (i = 0x80000002; i <= 0x80000004; i++) {
Jordan Crouse7249f792008-03-20 00:11:05 +0000159 docpuid(i, &eax, &ebx, &ecx, &edx);
160
161 if (eax == 0)
162 break;
163
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000164 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000165 *p++ = eax >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000166 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000167 *p++ = ebx >> (8 * t);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000168 for (t = 0; t < 4; t++)
Jordan Crouse7249f792008-03-20 00:11:05 +0000169 *p++ = ecx >> (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++ = edx >> (8 * t);
172 }
173
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000174 mvwprintw(win, row, 1, "Processor: %s", name);
Jordan Crouse7249f792008-03-20 00:11:05 +0000175}
176
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000177static int cpuinfo_module_redraw(WINDOW *win)
Jordan Crouse7249f792008-03-20 00:11:05 +0000178{
179 unsigned long eax, ebx, ecx, edx;
Jordan Crouse7249f792008-03-20 00:11:05 +0000180 unsigned int brand;
Uwe Hermann35845a22008-03-20 20:05:22 +0000181 char *vstr;
Jordan Crouse7249f792008-03-20 00:11:05 +0000182 int row = 2;
183
184 print_module_title(win, "CPU Information");
185
186 docpuid(0, NULL, &vendor, NULL, NULL);
187
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000188 switch (vendor) {
189 case VENDOR_INTEL:
Jordan Crouse7249f792008-03-20 00:11:05 +0000190 vstr = "Intel";
191 break;
192 case VENDOR_AMD:
193 vstr = "AMD";
194 break;
195 case VENDOR_CYRIX:
196 vstr = "Cyrix";
197 break;
198 case VENDOR_IDT:
199 vstr = "IDT";
200 break;
201 case VENDOR_GEODE:
202 vstr = "NatSemi Geode";
203 break;
204 case VENDOR_RISE:
205 case VENDOR_RISE2:
206 vstr = "RISE";
207 break;
208 case VENDOR_SIS:
209 vstr = "SiS";
Uwe Hermann35845a22008-03-20 20:05:22 +0000210 break;
211 default:
212 vstr = "Unknown";
213 break;
Jordan Crouse7249f792008-03-20 00:11:05 +0000214 }
215
216 mvwprintw(win, row++, 1, "Vendor: %s", vstr);
217
218 do_name(win, row++);
219
220 docpuid(0x00000001, &eax, &ebx, &ecx, &edx);
221
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000222 mvwprintw(win, row++, 1, "Family: %X", (eax >> 8) & 0x0f);
Jordan Crouse7249f792008-03-20 00:11:05 +0000223 mvwprintw(win, row++, 1, "Model: %X",
224 ((eax >> 4) & 0xf) | ((eax >> 16) & 0xf) << 4);
225
226 mvwprintw(win, row++, 1, "Stepping: %X", eax & 0xf);
227
228 if (vendor == VENDOR_AMD) {
229 docpuid(0x80000001, &eax, &ebx, &ecx, &edx);
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000230 brand = ((ebx >> 9) & 0x1f);
Jordan Crouse7249f792008-03-20 00:11:05 +0000231
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000232 mvwprintw(win, row++, 1, "Brand: %X", brand);
Jordan Crouse7249f792008-03-20 00:11:05 +0000233 }
234
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000235 if (cpu_khz != 0)
236 mvwprintw(win, row++, 1, "CPU Speed: %d Mhz", cpu_khz / 1000);
237 else
Jordan Crouse7249f792008-03-20 00:11:05 +0000238 mvwprintw(win, row++, 1, "CPU Speed: Error");
Jordan Crouse7249f792008-03-20 00:11:05 +0000239
240 row++;
241 get_features(win, &row);
Uwe Hermann35845a22008-03-20 20:05:22 +0000242
243 return 0;
Jordan Crouse7249f792008-03-20 00:11:05 +0000244}
245
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000246static unsigned int getticks(void)
Jordan Crouse7249f792008-03-20 00:11:05 +0000247{
248 unsigned long long start, end;
249
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000250 /* Read the number of ticks during the period. */
Jordan Crouse7249f792008-03-20 00:11:05 +0000251 start = rdtsc();
252 mdelay(100);
253 end = rdtsc();
254
Uwe Hermann3a406fe2008-03-20 01:11:28 +0000255 return (unsigned int)((end - start) / 100);
Jordan Crouse7249f792008-03-20 00:11:05 +0000256}
257
Uwe Hermann0bfb5c42008-03-23 15:34:04 +0000258static int cpuinfo_module_init(void)
Jordan Crouse7249f792008-03-20 00:11:05 +0000259{
260 cpu_khz = getticks();
Uwe Hermann35845a22008-03-20 20:05:22 +0000261 return 0;
Jordan Crouse7249f792008-03-20 00:11:05 +0000262}
263
264struct coreinfo_module cpuinfo_module = {
265 .name = "CPU Info",
266 .init = cpuinfo_module_init,
267 .redraw = cpuinfo_module_redraw,
Jordan Crouse7249f792008-03-20 00:11:05 +0000268};
Uwe Hermannab5b3e02008-03-31 20:30:18 +0000269
270#else
271
272struct coreinfo_module cpuinfo_module = {
273};
274
275#endif