The Pedigree Project 0.1
CpuInfoCommand.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pedigree/kernel/Version.h"
21#include "pedigree/kernel/debugger/commands/CpuInfoCommand.h"
22#include "pedigree/kernel/processor/Processor.h"
23
24#if X86_COMMON && !HOSTED
25#include "pedigree/kernel/processor/x86_common/Processor.h"
26#endif
27
28namespace {
29void drawFooter(DebuggerIO* screen) {
30 NormalStaticString footer("j: up k: down backspace: page up space: page down q: quit");
31 footer.truncate(screen->getWidth());
32 screen->drawString(footer, screen->getHeight() - 1, 0, DebuggerIO::White, DebuggerIO::Green);
33}
34} // namespace
35
36CpuInfoCommand::CpuInfoCommand() : DebuggerCommand(), Scrollable(), m_Lines(), m_LineCount(0) {}
37
38CpuInfoCommand::~CpuInfoCommand() {}
39
41
43 InterruptState& state, DebuggerIO* screen) {
44 m_LineCount = 0;
45 m_Lines[m_LineCount++] = "CPU information";
46
47#if X86_COMMON && !HOSTED
48 uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
49 X86CommonProcessor::cpuid(0, 0, eax, ebx, ecx, edx);
50 const uint32_t maxLeaf = eax;
51 char vendor[13];
52 MemoryCopy(vendor, &ebx, sizeof(ebx));
53 MemoryCopy(vendor + 4, &edx, sizeof(edx));
54 MemoryCopy(vendor + 8, &ecx, sizeof(ecx));
55 vendor[12] = '\0';
56 m_Lines[m_LineCount++] = "Vendor: ";
57 m_Lines[m_LineCount - 1] += vendor;
58
59 if (maxLeaf >= 1) {
60 X86CommonProcessor::cpuid(1, 0, eax, ebx, ecx, edx);
61 const uint32_t baseFamily = (eax >> 8) & 0xf;
62 const uint32_t baseModel = (eax >> 4) & 0xf;
63 const uint32_t family = baseFamily == 0xf ? baseFamily + ((eax >> 20) & 0xff) : baseFamily;
64 const uint32_t model = (baseFamily == 0x6 || baseFamily == 0xf)
65 ? baseModel | (((eax >> 16) & 0xf) << 4)
66 : baseModel;
67 m_Lines[m_LineCount++] = "Family/model/stepping: ";
68 m_Lines[m_LineCount - 1].append(family, 10);
69 m_Lines[m_LineCount - 1] += "/";
70 m_Lines[m_LineCount - 1].append(model, 10);
71 m_Lines[m_LineCount - 1] += "/";
72 m_Lines[m_LineCount - 1].append(eax & 0xf, 10);
73 m_Lines[m_LineCount++] = "Logical CPUs reported: ";
74 m_Lines[m_LineCount - 1].append((ebx >> 16) & 0xff, 10);
75 m_Lines[m_LineCount++] = "Features: ";
76 if (edx & (1u << 25))
77 m_Lines[m_LineCount - 1] += "SSE ";
78 if (edx & (1u << 26))
79 m_Lines[m_LineCount - 1] += "SSE2 ";
80 if (ecx & (1u << 0))
81 m_Lines[m_LineCount - 1] += "SSE3 ";
82 if (ecx & (1u << 9))
83 m_Lines[m_LineCount - 1] += "SSSE3 ";
84 if (ecx & (1u << 19))
85 m_Lines[m_LineCount - 1] += "SSE4.1 ";
86 if (ecx & (1u << 20))
87 m_Lines[m_LineCount - 1] += "SSE4.2 ";
88 if (ecx & (1u << 28))
89 m_Lines[m_LineCount - 1] += "AVX ";
90 if (edx & (1u << 28))
91 m_Lines[m_LineCount - 1] += "HTT";
92 }
93
94 X86CommonProcessor::cpuid(0x80000000, 0, eax, ebx, ecx, edx);
95 if (eax >= 0x80000004) {
96 char brand[49];
97 for (uint32_t leaf = 0; leaf < 3; ++leaf) {
98 X86CommonProcessor::cpuid(0x80000002 + leaf, 0, eax, ebx, ecx, edx);
99 MemoryCopy(brand + leaf * 16, &eax, sizeof(eax));
100 MemoryCopy(brand + leaf * 16 + 4, &ebx, sizeof(ebx));
101 MemoryCopy(brand + leaf * 16 + 8, &ecx, sizeof(ecx));
102 MemoryCopy(brand + leaf * 16 + 12, &edx, sizeof(edx));
103 }
104 brand[48] = '\0';
105 for (size_t i = 48; i && brand[i - 1] == ' '; --i)
106 brand[i - 1] = '\0';
107 m_Lines[m_LineCount++] = "Name: ";
108 m_Lines[m_LineCount - 1] += brand;
109 }
110#else
113 m_Lines[m_LineCount++] = "Processor: ";
114 m_Lines[m_LineCount - 1] += identity;
115#endif
116
117 m_Lines[m_LineCount++] = "Online CPUs: ";
118 m_Lines[m_LineCount - 1].append(Processor::getCount(), 10);
119 m_Lines[m_LineCount++] = "Build revision: ";
120 m_Lines[m_LineCount - 1] += g_pBuildRevision;
121 m_Lines[m_LineCount++] = "Built by ";
122 m_Lines[m_LineCount - 1] += g_pBuildUser;
123 m_Lines[m_LineCount - 1] += " at ";
124 m_Lines[m_LineCount - 1] += g_pBuildTime;
125 m_Lines[m_LineCount - 1] += " on ";
126 m_Lines[m_LineCount - 1] += g_pBuildMachine;
127 m_Lines[m_LineCount++] = "Build target: ";
128 m_Lines[m_LineCount - 1] += g_pBuildTarget;
129 m_Lines[m_LineCount++] = "Build flags: ";
130 m_Lines[m_LineCount - 1] += g_pBuildFlags;
131
132 screen->disableCli();
133 move(0, 1);
134 resize(screen->getWidth(), screen->getHeight() - 2);
135 setScrollKeys('j', 'k');
136 screen->drawHorizontalLine(' ', 0, 0, screen->getWidth() - 1, DebuggerIO::White,
137 DebuggerIO::Green);
138 screen->drawString("Pedigree debugger - CPU/build info", 0, 0, DebuggerIO::White,
139 DebuggerIO::Green);
140 screen->drawHorizontalLine(' ', screen->getHeight() - 1, 0, screen->getWidth() - 1,
141 DebuggerIO::White, DebuggerIO::Green);
142 drawFooter(screen);
143
144 bool stop = false;
145 while (!stop) {
146 refresh(screen);
147 char c = 0;
148 while (!(c = screen->getChar()))
149 ;
150 if (c == 'j')
151 scroll(-1);
152 else if (c == 'k')
153 scroll(1);
154 else if (c == ' ')
155 scroll(static_cast<ssize_t>(height()));
156 else if (c == 0x08)
157 scroll(-static_cast<ssize_t>(height()));
158 else if (c == 'q')
159 stop = true;
160 }
161
162 screen->drawString(" ", 1, 0, DebuggerIO::White, DebuggerIO::Black);
163 screen->enableCli();
164 return true;
165}
166
170
171const char* CpuInfoCommand::getLine1(size_t index, DebuggerIO::Colour& colour,
172 DebuggerIO::Colour& bgColour) {
173 colour = DebuggerIO::White;
174 bgColour = DebuggerIO::Black;
175 return index < m_LineCount ? static_cast<const char*>(m_Lines[index]) : nullptr;
176}
177
178const char* CpuInfoCommand::getLine2(size_t index, size_t& colOffset, DebuggerIO::Colour& colour,
179 DebuggerIO::Colour& bgColour) {
180 colOffset = 0;
181 colour = DebuggerIO::Black;
182 bgColour = DebuggerIO::Black;
183 return "";
184}
185
186size_t CpuInfoCommand::getLineCount() {
187 return m_LineCount;
188}
bool execute(const HugeStaticString &input, HugeStaticString &output, InterruptState &state, DebuggerIO *screen)
void autocomplete(const HugeStaticString &input, HugeStaticString &output)
const NormalStaticString getString()
virtual void enableCli()=0
virtual void drawString(const char *str, size_t row, size_t col, Colour foreColour, Colour backColour)=0
virtual size_t getWidth()=0
virtual void drawHorizontalLine(char c, size_t row, size_t colStart, size_t colEnd, Colour foreColour, Colour backColour)=0
virtual char getChar()=0
static void identify(HugeStaticString &str)
static size_t getCount()
static void cpuid(uint32_t inEax, uint32_t inEcx, uint32_t &eax, uint32_t &ebx, uint32_t &ecx, uint32_t &edx)