VirtualBox

source: vbox/trunk/src/VBox/VMM/tools/VBoxCpuReport.cpp@ 109008

Last change on this file since 109008 was 109008, checked in by vboxsync, 5 days ago

VMM,Main: Working on ARM CPU profile support, which is neede/useful for getting info about the host CPU as well. The CPUDBENTRY typedef is used externally by Main, so we can't have two definitions of it, so left the bits that are common to both x86 and ARM in CPUDBENTRY and created sub-structures for each of the two targets/platforms. Also started reworking the VBoxCpuReport tool so we can use it on arm as well (much left to do there, though). jiraref:VBP-1598

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.8 KB
Line 
1/* $Id: VBoxCpuReport.cpp 109008 2025-04-16 20:59:36Z vboxsync $ */
2/** @file
3 * VBoxCpuReport - Produces the basis for a CPU DB entry.
4 */
5
6/*
7 * Copyright (C) 2013-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <iprt/asm.h>
33#include <iprt/buildconfig.h>
34#include <iprt/ctype.h>
35#include <iprt/errcore.h>
36#include <iprt/file.h>
37#include <iprt/getopt.h>
38#include <iprt/initterm.h>
39#include <iprt/message.h>
40#include <iprt/mem.h>
41#include <iprt/path.h>
42#include <iprt/string.h>
43#include <iprt/stream.h>
44#include <iprt/symlink.h>
45#include <iprt/thread.h>
46#include <iprt/time.h>
47
48#include <VBox/vmm/cpum.h>
49#include <VBox/sup.h>
50#include <VBox/version.h>
51
52#include "VBoxCpuReport.h"
53
54
55/*********************************************************************************************************************************
56* Global Variables *
57*********************************************************************************************************************************/
58/** The alternative report stream. */
59PRTSTREAM g_pReportOut;
60/** The alternative debug stream. */
61PRTSTREAM g_pDebugOut;
62/** The CPU vendor. Used by the MSR code. */
63CPUMCPUVENDOR g_enmVendor = CPUMCPUVENDOR_INVALID;
64/** The CPU microarchitecture. Used by the MSR code. */
65CPUMMICROARCH g_enmMicroarch = kCpumMicroarch_Invalid;
66
67
68
69void vbCpuRepDebug(const char *pszMsg, ...)
70{
71 va_list va;
72
73 /* Always print a copy of the report to standard error. */
74 va_start(va, pszMsg);
75 RTStrmPrintfV(g_pStdErr, pszMsg, va);
76 va_end(va);
77 RTStrmFlush(g_pStdErr);
78
79 /* Alternatively, also print to a log file. */
80 if (g_pDebugOut)
81 {
82 va_start(va, pszMsg);
83 RTStrmPrintfV(g_pDebugOut, pszMsg, va);
84 va_end(va);
85 RTStrmFlush(g_pDebugOut);
86 }
87
88 /* Give the output device a chance to write / display it. */
89 RTThreadSleep(1);
90}
91
92
93void vbCpuRepPrintf(const char *pszMsg, ...)
94{
95 va_list va;
96
97 /* Output to report file, if requested. */
98 if (g_pReportOut)
99 {
100 va_start(va, pszMsg);
101 RTStrmPrintfV(g_pReportOut, pszMsg, va);
102 va_end(va);
103 RTStrmFlush(g_pReportOut);
104 }
105
106 /* Always print a copy of the report to standard out. */
107 va_start(va, pszMsg);
108 RTStrmPrintfV(g_pStdOut, pszMsg, va);
109 va_end(va);
110 RTStrmFlush(g_pStdOut);
111}
112
113
114
115const char *vbCpuVendorToString(CPUMCPUVENDOR enmCpuVendor)
116{
117 switch (enmCpuVendor)
118 {
119 case CPUMCPUVENDOR_INTEL: return "Intel";
120 case CPUMCPUVENDOR_AMD: return "AMD";
121 case CPUMCPUVENDOR_VIA: return "VIA";
122 case CPUMCPUVENDOR_CYRIX: return "Cyrix";
123 case CPUMCPUVENDOR_SHANGHAI: return "Shanghai";
124 case CPUMCPUVENDOR_HYGON: return "Hygon";
125 case CPUMCPUVENDOR_APPLE: return "Apple";
126 case CPUMCPUVENDOR_INVALID:
127 case CPUMCPUVENDOR_UNKNOWN:
128 case CPUMCPUVENDOR_32BIT_HACK:
129 break;
130 }
131 return "invalid-cpu-vendor";
132}
133
134
135int main(int argc, char **argv)
136{
137 int rc = RTR3InitExe(argc, &argv, 0 /*fFlags*/);
138 if (RT_FAILURE(rc))
139 return RTMsgInitFailure(rc);
140
141 /*
142 * Argument parsing?
143 */
144 static const RTGETOPTDEF s_aOptions[] =
145 {
146#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
147 { "--msrs-only", 'm', RTGETOPT_REQ_NOTHING },
148 { "--msrs-dev", 'd', RTGETOPT_REQ_NOTHING },
149 { "--no-msrs", 'n', RTGETOPT_REQ_NOTHING },
150#endif
151 { "--output", 'o', RTGETOPT_REQ_STRING },
152 { "--log", 'l', RTGETOPT_REQ_STRING },
153 };
154 RTGETOPTSTATE State;
155 RTGetOptInit(&State, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
156
157 enum
158 {
159 kCpuReportOp_Normal,
160#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
161 kCpuReportOp_MsrsOnly,
162 kCpuReportOp_MsrsHacking
163#else
164 kCpuReportOp_Dummy
165#endif
166 } enmOp = kCpuReportOp_Normal;
167 g_pReportOut = NULL;
168 g_pDebugOut = NULL;
169 const char *pszOutput = NULL;
170 const char *pszDebugOut = NULL;
171
172 int iOpt;
173 RTGETOPTUNION ValueUnion;
174 while ((iOpt = RTGetOpt(&State, &ValueUnion)) != 0)
175 {
176 switch (iOpt)
177 {
178#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
179 case 'm':
180 enmOp = kCpuReportOp_MsrsOnly;
181 break;
182
183 case 'd':
184 enmOp = kCpuReportOp_MsrsHacking;
185 break;
186
187 case 'n':
188 g_fNoMsrs = true;
189 break;
190#endif
191
192 case 'o':
193 pszOutput = ValueUnion.psz;
194 break;
195
196 case 'l':
197 pszDebugOut = ValueUnion.psz;
198 break;
199
200 case 'h':
201 {
202#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
203 const char * const pszArchOps = "[-m|--msrs-only] [-d|--msrs-dev] [-n|--no-msrs] ";
204#else
205 const char * const pszArchOps = "";
206#endif
207 RTPrintf("Usage: VBoxCpuReport %s[-h|--help] [-V|--version] [-o filename.h] [-l debug.log]\n",
208 pszArchOps);
209 RTPrintf("Internal tool for gathering information to the VMM CPU database.\n");
210 return RTEXITCODE_SUCCESS;
211 }
212 case 'V':
213 RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
214 return RTEXITCODE_SUCCESS;
215 default:
216 return RTGetOptPrintError(iOpt, &ValueUnion);
217 }
218 }
219
220 /*
221 * Open the alternative debug log stream.
222 */
223 if (pszDebugOut)
224 {
225 if (RTFileExists(pszDebugOut) && !RTSymlinkExists(pszDebugOut))
226 {
227 char szOld[RTPATH_MAX];
228 rc = RTStrCopy(szOld, sizeof(szOld), pszDebugOut);
229 if (RT_SUCCESS(rc))
230 rc = RTStrCat(szOld, sizeof(szOld), ".old");
231 if (RT_SUCCESS(rc))
232 RTFileRename(pszDebugOut, szOld, RTFILEMOVE_FLAGS_REPLACE);
233 }
234 rc = RTStrmOpen(pszDebugOut, "w", &g_pDebugOut);
235 if (RT_FAILURE(rc))
236 {
237 RTMsgError("Error opening '%s': %Rrc", pszDebugOut, rc);
238 g_pDebugOut = NULL;
239 }
240 }
241
242 /*
243 * Do the requested job.
244 */
245 rc = VERR_INTERNAL_ERROR;
246 switch (enmOp)
247 {
248 case kCpuReportOp_Normal:
249 /* switch output file. */
250 if (pszOutput)
251 {
252 if (RTFileExists(pszOutput) && !RTSymlinkExists(pszOutput))
253 {
254 char szOld[RTPATH_MAX];
255 rc = RTStrCopy(szOld, sizeof(szOld), pszOutput);
256 if (RT_SUCCESS(rc))
257 rc = RTStrCat(szOld, sizeof(szOld), ".old");
258 if (RT_SUCCESS(rc))
259 RTFileRename(pszOutput, szOld, RTFILEMOVE_FLAGS_REPLACE);
260 }
261 rc = RTStrmOpen(pszOutput, "w", &g_pReportOut);
262 if (RT_FAILURE(rc))
263 {
264 RTMsgError("Error opening '%s': %Rrc", pszOutput, rc);
265 break;
266 }
267 }
268 rc = produceCpuReport();
269 break;
270#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
271 case kCpuReportOp_MsrsOnly:
272 case kCpuReportOp_MsrsHacking:
273 rc = probeMsrs(enmOp == kCpuReportOp_MsrsHacking, NULL, NULL, NULL, 0);
274 break;
275#else
276 case kCpuReportOp_Dummy:
277 break;
278#endif
279 }
280
281 /*
282 * Close the output files.
283 */
284 if (g_pReportOut)
285 {
286 RTStrmClose(g_pReportOut);
287 g_pReportOut = NULL;
288 }
289
290 if (g_pDebugOut)
291 {
292 RTStrmClose(g_pDebugOut);
293 g_pDebugOut = NULL;
294 }
295
296 return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
297}
298
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette