VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/CPUM-armv8.cpp@ 100524

Last change on this file since 100524 was 99956, checked in by vboxsync, 20 months ago

VMM/CPUM-armv8: Implement OSDLR_EL1, OSLAR_EL1 and OSLSR_EL1 accessed by Linux guests, bugref:10387

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.3 KB
Line 
1/* $Id: CPUM-armv8.cpp 99956 2023-05-24 11:39:15Z vboxsync $ */
2/** @file
3 * CPUM - CPU Monitor / Manager (ARMv8 variant).
4 */
5
6/*
7 * Copyright (C) 2023 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/** @page pg_cpum CPUM - CPU Monitor / Manager
29 *
30 * The CPU Monitor / Manager keeps track of all the CPU registers.
31 * This is the ARMv8 variant which is doing much less than its x86/amd64
32 * counterpart due to the fact that we currently only support the NEM backends
33 * for running ARM guests. It might become complex iff we decide to implement our
34 * own hypervisor.
35 *
36 * @section sec_cpum_logging_armv8 Logging Level Assignments.
37 *
38 * Following log level assignments:
39 * - @todo
40 *
41 */
42
43
44/*********************************************************************************************************************************
45* Header Files *
46*********************************************************************************************************************************/
47#define LOG_GROUP LOG_GROUP_CPUM
48#define CPUM_WITH_NONCONST_HOST_FEATURES
49#include <VBox/vmm/cpum.h>
50#include <VBox/vmm/cpumdis.h>
51#include <VBox/vmm/pgm.h>
52#include <VBox/vmm/mm.h>
53#include <VBox/vmm/em.h>
54#include <VBox/vmm/iem.h>
55#include <VBox/vmm/dbgf.h>
56#include <VBox/vmm/ssm.h>
57#include "CPUMInternal-armv8.h"
58#include <VBox/vmm/vm.h>
59
60#include <VBox/param.h>
61#include <VBox/dis.h>
62#include <VBox/err.h>
63#include <VBox/log.h>
64#include <iprt/assert.h>
65#include <iprt/cpuset.h>
66#include <iprt/mem.h>
67#include <iprt/mp.h>
68#include <iprt/string.h>
69#include <iprt/armv8.h>
70
71
72/*********************************************************************************************************************************
73* Defined Constants And Macros *
74*********************************************************************************************************************************/
75
76/** Internal form used by the macros. */
77#ifdef VBOX_WITH_STATISTICS
78# define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
79 { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName, \
80 { 0 }, { 0 }, { 0 }, { 0 } }
81#else
82# define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
83 { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName }
84#endif
85
86/** Function handlers, extended version. */
87#define MFX(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uValue, a_fWrIgnMask, a_fWrGpMask) \
88 RINT(a_uMsr, a_uMsr, kCpumSysRegRdFn_##a_enmRdFnSuff, kCpumSysRegWrFn_##a_enmWrFnSuff, 0, a_uValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
89/** Function handlers, read-only. */
90#define MFO(a_uMsr, a_szName, a_enmRdFnSuff) \
91 RINT(a_uMsr, a_uMsr, kCpumSysRegRdFn_##a_enmRdFnSuff, kCpumSysRegWrFn_ReadOnly, 0, 0, 0, UINT64_MAX, a_szName)
92/** Read-only fixed value, ignores all writes. */
93#define MVI(a_uMsr, a_szName, a_uValue) \
94 RINT(a_uMsr, a_uMsr, kCpumSysRegRdFn_FixedValue, kCpumSysRegWrFn_IgnoreWrite, 0, a_uValue, UINT64_MAX, 0, a_szName)
95
96
97/*********************************************************************************************************************************
98* Structures and Typedefs *
99*********************************************************************************************************************************/
100
101/**
102 * What kind of cpu info dump to perform.
103 */
104typedef enum CPUMDUMPTYPE
105{
106 CPUMDUMPTYPE_TERSE,
107 CPUMDUMPTYPE_DEFAULT,
108 CPUMDUMPTYPE_VERBOSE
109} CPUMDUMPTYPE;
110/** Pointer to a cpu info dump type. */
111typedef CPUMDUMPTYPE *PCPUMDUMPTYPE;
112
113
114/*********************************************************************************************************************************
115* Internal Functions *
116*********************************************************************************************************************************/
117static DECLCALLBACK(int) cpumR3LiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass);
118static DECLCALLBACK(int) cpumR3SaveExec(PVM pVM, PSSMHANDLE pSSM);
119static DECLCALLBACK(int) cpumR3LoadPrep(PVM pVM, PSSMHANDLE pSSM);
120static DECLCALLBACK(int) cpumR3LoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
121static DECLCALLBACK(int) cpumR3LoadDone(PVM pVM, PSSMHANDLE pSSM);
122static DECLCALLBACK(void) cpumR3InfoAll(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
123static DECLCALLBACK(void) cpumR3InfoGuest(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
124static DECLCALLBACK(void) cpumR3InfoGuestInstr(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
125
126
127/*********************************************************************************************************************************
128* Global Variables *
129*********************************************************************************************************************************/
130/**
131 * System register ranges.
132 */
133static CPUMSYSREGRANGE const g_aSysRegRanges[] =
134{
135 MFX(ARMV8_AARCH64_SYSREG_OSLAR_EL1, "OSLAR_EL1", WriteOnly, OslarEl1, 0, UINT64_C(0xfffffffffffffffe), UINT64_C(0xfffffffffffffffe)),
136 MFO(ARMV8_AARCH64_SYSREG_OSLSR_EL1, "OSLSR_EL1", OslsrEl1),
137 MVI(ARMV8_AARCH64_SYSREG_OSDLR_EL1, "OSDLR_EL1", 0)
138};
139
140
141#if 0 /** @todo Will come later. */
142/** Saved state field descriptors for CPUMCTX. */
143static const SSMFIELD g_aCpumCtxFields[] =
144{
145 SSMFIELD_ENTRY( CPUMCTX, aGRegs[0].x),
146 SSMFIELD_ENTRY( CPUMCTX, aGRegs[1].x),
147 SSMFIELD_ENTRY( CPUMCTX, aGRegs[2].x),
148 SSMFIELD_ENTRY( CPUMCTX, aGRegs[3].x),
149 SSMFIELD_ENTRY( CPUMCTX, aGRegs[4].x),
150 SSMFIELD_ENTRY( CPUMCTX, aGRegs[5].x),
151 SSMFIELD_ENTRY( CPUMCTX, aGRegs[6].x),
152 SSMFIELD_ENTRY( CPUMCTX, aGRegs[7].x),
153 SSMFIELD_ENTRY( CPUMCTX, aGRegs[8].x),
154 SSMFIELD_ENTRY( CPUMCTX, aGRegs[9].x),
155 SSMFIELD_ENTRY( CPUMCTX, aGRegs[10].x),
156 SSMFIELD_ENTRY( CPUMCTX, aGRegs[11].x),
157 SSMFIELD_ENTRY( CPUMCTX, aGRegs[12].x),
158 SSMFIELD_ENTRY( CPUMCTX, aGRegs[13].x),
159 SSMFIELD_ENTRY( CPUMCTX, aGRegs[14].x),
160 SSMFIELD_ENTRY( CPUMCTX, aGRegs[15].x),
161 SSMFIELD_ENTRY( CPUMCTX, aGRegs[16].x),
162 SSMFIELD_ENTRY( CPUMCTX, aGRegs[17].x),
163 SSMFIELD_ENTRY( CPUMCTX, aGRegs[18].x),
164 SSMFIELD_ENTRY( CPUMCTX, aGRegs[19].x),
165 SSMFIELD_ENTRY( CPUMCTX, aGRegs[20].x),
166 SSMFIELD_ENTRY( CPUMCTX, aGRegs[21].x),
167 SSMFIELD_ENTRY( CPUMCTX, aGRegs[22].x),
168 SSMFIELD_ENTRY( CPUMCTX, aGRegs[23].x),
169 SSMFIELD_ENTRY( CPUMCTX, aGRegs[24].x),
170 SSMFIELD_ENTRY( CPUMCTX, aGRegs[25].x),
171 SSMFIELD_ENTRY( CPUMCTX, aGRegs[26].x),
172 SSMFIELD_ENTRY( CPUMCTX, aGRegs[27].x),
173 SSMFIELD_ENTRY( CPUMCTX, aGRegs[28].x),
174 SSMFIELD_ENTRY( CPUMCTX, aGRegs[29].x),
175 SSMFIELD_ENTRY( CPUMCTX, aGRegs[30].x),
176 SSMFIELD_ENTRY( CPUMCTX, aVRegs[0].v),
177 SSMFIELD_ENTRY( CPUMCTX, aVRegs[1].v),
178 SSMFIELD_ENTRY( CPUMCTX, aVRegs[2].v),
179 SSMFIELD_ENTRY( CPUMCTX, aVRegs[3].v),
180 SSMFIELD_ENTRY( CPUMCTX, aVRegs[4].v),
181 SSMFIELD_ENTRY( CPUMCTX, aVRegs[5].v),
182 SSMFIELD_ENTRY( CPUMCTX, aVRegs[6].v),
183 SSMFIELD_ENTRY( CPUMCTX, aVRegs[7].v),
184 SSMFIELD_ENTRY( CPUMCTX, aVRegs[8].v),
185 SSMFIELD_ENTRY( CPUMCTX, aVRegs[9].v),
186 SSMFIELD_ENTRY( CPUMCTX, aVRegs[10].v),
187 SSMFIELD_ENTRY( CPUMCTX, aVRegs[11].v),
188 SSMFIELD_ENTRY( CPUMCTX, aVRegs[12].v),
189 SSMFIELD_ENTRY( CPUMCTX, aVRegs[13].v),
190 SSMFIELD_ENTRY( CPUMCTX, aVRegs[14].v),
191 SSMFIELD_ENTRY( CPUMCTX, aVRegs[15].v),
192 SSMFIELD_ENTRY( CPUMCTX, aVRegs[16].v),
193 SSMFIELD_ENTRY( CPUMCTX, aVRegs[17].v),
194 SSMFIELD_ENTRY( CPUMCTX, aVRegs[18].v),
195 SSMFIELD_ENTRY( CPUMCTX, aVRegs[19].v),
196 SSMFIELD_ENTRY( CPUMCTX, aVRegs[20].v),
197 SSMFIELD_ENTRY( CPUMCTX, aVRegs[21].v),
198 SSMFIELD_ENTRY( CPUMCTX, aVRegs[22].v),
199 SSMFIELD_ENTRY( CPUMCTX, aVRegs[23].v),
200 SSMFIELD_ENTRY( CPUMCTX, aVRegs[24].v),
201 SSMFIELD_ENTRY( CPUMCTX, aVRegs[25].v),
202 SSMFIELD_ENTRY( CPUMCTX, aVRegs[26].v),
203 SSMFIELD_ENTRY( CPUMCTX, aVRegs[27].v),
204 SSMFIELD_ENTRY( CPUMCTX, aVRegs[28].v),
205 SSMFIELD_ENTRY( CPUMCTX, aVRegs[29].v),
206 SSMFIELD_ENTRY( CPUMCTX, aVRegs[30].v),
207 SSMFIELD_ENTRY( CPUMCTX, aVRegs[31].v),
208 SSMFIELD_ENTRY( CPUMCTX, aSpReg[0].u64),
209 SSMFIELD_ENTRY( CPUMCTX, aSpReg[1].u64),
210 SSMFIELD_ENTRY( CPUMCTX, Pc.u64),
211 SSMFIELD_ENTRY( CPUMCTX, Spsr.u64),
212 SSMFIELD_ENTRY( CPUMCTX, Elr.u64),
213 SSMFIELD_ENTRY( CPUMCTX, fpcr),
214 SSMFIELD_ENTRY( CPUMCTX, fpsr),
215 SSMFIELD_ENTRY( CPUMCTX, fPState),
216 /** @todo */
217 SSMFIELD_ENTRY_TERM()
218};
219#endif
220
221
222/**
223 * Initializes the guest system register states.
224 *
225 * @returns VBox status code.
226 * @param pVM The cross context VM structure.
227 */
228static int cpumR3InitSysRegs(PVM pVM)
229{
230 for (uint32_t i = 0; i < RT_ELEMENTS(g_aSysRegRanges); i++)
231 {
232 int rc = CPUMR3SysRegRangesInsert(pVM, &g_aSysRegRanges[i]);
233 AssertLogRelRCReturn(rc, rc);
234 }
235
236 return VINF_SUCCESS;
237}
238
239
240/**
241 * Initializes the CPUM.
242 *
243 * @returns VBox status code.
244 * @param pVM The cross context VM structure.
245 */
246VMMR3DECL(int) CPUMR3Init(PVM pVM)
247{
248 LogFlow(("CPUMR3Init\n"));
249
250 /*
251 * Assert alignment, sizes and tables.
252 */
253 AssertCompileMemberAlignment(VM, cpum.s, 32);
254 AssertCompile(sizeof(pVM->cpum.s) <= sizeof(pVM->cpum.padding));
255 AssertCompileSizeAlignment(CPUMCTX, 64);
256 AssertCompileMemberAlignment(VM, cpum, 64);
257 AssertCompileMemberAlignment(VMCPU, cpum.s, 64);
258#ifdef VBOX_STRICT
259 int rc2 = cpumR3SysRegStrictInitChecks();
260 AssertRCReturn(rc2, rc2);
261#endif
262
263 pVM->cpum.s.GuestInfo.paSysRegRangesR3 = &pVM->cpum.s.GuestInfo.aSysRegRanges[0];
264
265 /*
266 * Register saved state data item.
267 */
268 int rc = SSMR3RegisterInternal(pVM, "cpum", 1, CPUM_SAVED_STATE_VERSION, sizeof(CPUM),
269 NULL, cpumR3LiveExec, NULL,
270 NULL, cpumR3SaveExec, NULL,
271 cpumR3LoadPrep, cpumR3LoadExec, cpumR3LoadDone);
272 if (RT_FAILURE(rc))
273 return rc;
274
275 /*
276 * Register info handlers and registers with the debugger facility.
277 */
278 DBGFR3InfoRegisterInternalEx(pVM, "cpum", "Displays the all the cpu states.",
279 &cpumR3InfoAll, DBGFINFO_FLAGS_ALL_EMTS);
280 DBGFR3InfoRegisterInternalEx(pVM, "cpumguest", "Displays the guest cpu state.",
281 &cpumR3InfoGuest, DBGFINFO_FLAGS_ALL_EMTS);
282
283 rc = cpumR3DbgInit(pVM);
284 if (RT_FAILURE(rc))
285 return rc;
286
287 /*
288 * Initialize the Guest system register states.
289 */
290 rc = cpumR3InitSysRegs(pVM);
291 if (RT_FAILURE(rc))
292 return rc;
293
294 /*
295 * Initialize the general guest CPU state.
296 */
297 CPUMR3Reset(pVM);
298
299 return VINF_SUCCESS;
300}
301
302
303/**
304 * Applies relocations to data and code managed by this
305 * component. This function will be called at init and
306 * whenever the VMM need to relocate it self inside the GC.
307 *
308 * The CPUM will update the addresses used by the switcher.
309 *
310 * @param pVM The cross context VM structure.
311 */
312VMMR3DECL(void) CPUMR3Relocate(PVM pVM)
313{
314 RT_NOREF(pVM);
315}
316
317
318/**
319 * Terminates the CPUM.
320 *
321 * Termination means cleaning up and freeing all resources,
322 * the VM it self is at this point powered off or suspended.
323 *
324 * @returns VBox status code.
325 * @param pVM The cross context VM structure.
326 */
327VMMR3DECL(int) CPUMR3Term(PVM pVM)
328{
329 RT_NOREF(pVM);
330 return VINF_SUCCESS;
331}
332
333
334/**
335 * Resets a virtual CPU.
336 *
337 * Used by CPUMR3Reset and CPU hot plugging.
338 *
339 * @param pVM The cross context VM structure.
340 * @param pVCpu The cross context virtual CPU structure of the CPU that is
341 * being reset. This may differ from the current EMT.
342 */
343VMMR3DECL(void) CPUMR3ResetCpu(PVM pVM, PVMCPU pVCpu)
344{
345 RT_NOREF(pVM);
346
347 /** @todo anything different for VCPU > 0? */
348 PCPUMCTX pCtx = &pVCpu->cpum.s.Guest;
349
350 /*
351 * Initialize everything to ZERO first.
352 */
353 RT_BZERO(pCtx, sizeof(*pCtx));
354
355 /* Start in Supervisor mode. */
356 /** @todo Differentiate between Aarch64 and Aarch32 configuation. */
357 pCtx->fPState = ARMV8_SPSR_EL2_AARCH64_SET_EL(ARMV8_AARCH64_EL_1)
358 | ARMV8_SPSR_EL2_AARCH64_SP
359 | ARMV8_SPSR_EL2_AARCH64_D
360 | ARMV8_SPSR_EL2_AARCH64_A
361 | ARMV8_SPSR_EL2_AARCH64_I
362 | ARMV8_SPSR_EL2_AARCH64_F;
363 /** @todo */
364}
365
366
367/**
368 * Resets the CPU.
369 *
370 * @param pVM The cross context VM structure.
371 */
372VMMR3DECL(void) CPUMR3Reset(PVM pVM)
373{
374 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
375 {
376 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
377 CPUMR3ResetCpu(pVM, pVCpu);
378 }
379}
380
381
382
383
384/**
385 * Pass 0 live exec callback.
386 *
387 * @returns VINF_SSM_DONT_CALL_AGAIN.
388 * @param pVM The cross context VM structure.
389 * @param pSSM The saved state handle.
390 * @param uPass The pass (0).
391 */
392static DECLCALLBACK(int) cpumR3LiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
393{
394 AssertReturn(uPass == 0, VERR_SSM_UNEXPECTED_PASS);
395 /** @todo */ RT_NOREF(pVM, pSSM);
396 return VINF_SSM_DONT_CALL_AGAIN;
397}
398
399
400/**
401 * Execute state save operation.
402 *
403 * @returns VBox status code.
404 * @param pVM The cross context VM structure.
405 * @param pSSM SSM operation handle.
406 */
407static DECLCALLBACK(int) cpumR3SaveExec(PVM pVM, PSSMHANDLE pSSM)
408{
409 /*
410 * Save.
411 */
412 SSMR3PutU32(pSSM, pVM->cCpus);
413 /** @todo */
414 return VINF_SUCCESS;
415}
416
417
418/**
419 * @callback_method_impl{FNSSMINTLOADPREP}
420 */
421static DECLCALLBACK(int) cpumR3LoadPrep(PVM pVM, PSSMHANDLE pSSM)
422{
423 RT_NOREF(pSSM);
424 pVM->cpum.s.fPendingRestore = true;
425 return VINF_SUCCESS;
426}
427
428
429/**
430 * @callback_method_impl{FNSSMINTLOADEXEC}
431 */
432static DECLCALLBACK(int) cpumR3LoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
433{
434 /*
435 * Validate version.
436 */
437 /** @todo */ RT_NOREF(pSSM, uVersion);
438
439 if (uPass == SSM_PASS_FINAL)
440 {
441 /** @todo */
442 }
443
444 pVM->cpum.s.fPendingRestore = false;
445 return VINF_SUCCESS;
446}
447
448
449/**
450 * @callback_method_impl{FNSSMINTLOADDONE}
451 */
452static DECLCALLBACK(int) cpumR3LoadDone(PVM pVM, PSSMHANDLE pSSM)
453{
454 if (RT_FAILURE(SSMR3HandleGetStatus(pSSM)))
455 return VINF_SUCCESS;
456
457 /* just check this since we can. */ /** @todo Add a SSM unit flag for indicating that it's mandatory during a restore. */
458 if (pVM->cpum.s.fPendingRestore)
459 {
460 LogRel(("CPUM: Missing state!\n"));
461 return VERR_INTERNAL_ERROR_2;
462 }
463
464 /** @todo */
465 return VINF_SUCCESS;
466}
467
468
469/**
470 * Checks if the CPUM state restore is still pending.
471 *
472 * @returns true / false.
473 * @param pVM The cross context VM structure.
474 */
475VMMDECL(bool) CPUMR3IsStateRestorePending(PVM pVM)
476{
477 return pVM->cpum.s.fPendingRestore;
478}
479
480
481/**
482 * Formats the PSTATE value into mnemonics.
483 *
484 * @param pszPState Where to write the mnemonics. (Assumes sufficient buffer space.)
485 * @param fPState The PSTATE value with both guest hardware and VBox
486 * internal bits included.
487 */
488static void cpumR3InfoFormatPState(char *pszPState, uint32_t fPState)
489{
490 /*
491 * Format the flags.
492 */
493 static const struct
494 {
495 const char *pszSet; const char *pszClear; uint32_t fFlag;
496 } s_aFlags[] =
497 {
498 { NULL, NULL, 0 }, /** @todo */
499 };
500 char *psz = pszPState;
501 for (unsigned i = 0; i < RT_ELEMENTS(s_aFlags); i++)
502 {
503 const char *pszAdd = s_aFlags[i].fFlag & fPState ? s_aFlags[i].pszSet : s_aFlags[i].pszClear;
504 if (pszAdd)
505 {
506 strcpy(psz, pszAdd);
507 psz += strlen(pszAdd);
508 *psz++ = ' ';
509 }
510 }
511 psz[-1] = '\0';
512}
513
514
515/**
516 * Formats a full register dump.
517 *
518 * @param pVM The cross context VM structure.
519 * @param pCtx The context to format.
520 * @param pHlp Output functions.
521 * @param enmType The dump type.
522 * @param pszPrefix Register name prefix.
523 */
524static void cpumR3InfoOne(PVM pVM, PCPUMCTX pCtx, PCDBGFINFOHLP pHlp, CPUMDUMPTYPE enmType, const char *pszPrefix)
525{
526 RT_NOREF(pVM, pHlp, enmType, pszPrefix);
527
528 /*
529 * Format the PSTATE.
530 */
531 char szPState[80];
532 cpumR3InfoFormatPState(&szPState[0], pCtx->fPState);
533
534 /** @todo */
535}
536
537
538/**
539 * Display all cpu states and any other cpum info.
540 *
541 * @param pVM The cross context VM structure.
542 * @param pHlp The info helper functions.
543 * @param pszArgs Arguments, ignored.
544 */
545static DECLCALLBACK(void) cpumR3InfoAll(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
546{
547 cpumR3InfoGuest(pVM, pHlp, pszArgs);
548 cpumR3InfoGuestInstr(pVM, pHlp, pszArgs);
549}
550
551
552/**
553 * Parses the info argument.
554 *
555 * The argument starts with 'verbose', 'terse' or 'default' and then
556 * continues with the comment string.
557 *
558 * @param pszArgs The pointer to the argument string.
559 * @param penmType Where to store the dump type request.
560 * @param ppszComment Where to store the pointer to the comment string.
561 */
562static void cpumR3InfoParseArg(const char *pszArgs, CPUMDUMPTYPE *penmType, const char **ppszComment)
563{
564 if (!pszArgs)
565 {
566 *penmType = CPUMDUMPTYPE_DEFAULT;
567 *ppszComment = "";
568 }
569 else
570 {
571 if (!strncmp(pszArgs, RT_STR_TUPLE("verbose")))
572 {
573 pszArgs += 7;
574 *penmType = CPUMDUMPTYPE_VERBOSE;
575 }
576 else if (!strncmp(pszArgs, RT_STR_TUPLE("terse")))
577 {
578 pszArgs += 5;
579 *penmType = CPUMDUMPTYPE_TERSE;
580 }
581 else if (!strncmp(pszArgs, RT_STR_TUPLE("default")))
582 {
583 pszArgs += 7;
584 *penmType = CPUMDUMPTYPE_DEFAULT;
585 }
586 else
587 *penmType = CPUMDUMPTYPE_DEFAULT;
588 *ppszComment = RTStrStripL(pszArgs);
589 }
590}
591
592
593/**
594 * Display the guest cpu state.
595 *
596 * @param pVM The cross context VM structure.
597 * @param pHlp The info helper functions.
598 * @param pszArgs Arguments.
599 */
600static DECLCALLBACK(void) cpumR3InfoGuest(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
601{
602 CPUMDUMPTYPE enmType;
603 const char *pszComment;
604 cpumR3InfoParseArg(pszArgs, &enmType, &pszComment);
605
606 PVMCPU pVCpu = VMMGetCpu(pVM);
607 if (!pVCpu)
608 pVCpu = pVM->apCpusR3[0];
609
610 pHlp->pfnPrintf(pHlp, "Guest CPUM (VCPU %d) state: %s\n", pVCpu->idCpu, pszComment);
611
612 PCPUMCTX pCtx = &pVCpu->cpum.s.Guest;
613 cpumR3InfoOne(pVM, pCtx, pHlp, enmType, "");
614}
615
616
617/**
618 * Display the current guest instruction
619 *
620 * @param pVM The cross context VM structure.
621 * @param pHlp The info helper functions.
622 * @param pszArgs Arguments, ignored.
623 */
624static DECLCALLBACK(void) cpumR3InfoGuestInstr(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
625{
626 NOREF(pszArgs);
627
628 PVMCPU pVCpu = VMMGetCpu(pVM);
629 if (!pVCpu)
630 pVCpu = pVM->apCpusR3[0];
631
632 char szInstruction[256];
633 szInstruction[0] = '\0';
634 DBGFR3DisasInstrCurrent(pVCpu, szInstruction, sizeof(szInstruction));
635 pHlp->pfnPrintf(pHlp, "\nCPUM%u: %s\n\n", pVCpu->idCpu, szInstruction);
636}
637
638
639/**
640 * Called when the ring-3 init phase completes.
641 *
642 * @returns VBox status code.
643 * @param pVM The cross context VM structure.
644 * @param enmWhat Which init phase.
645 */
646VMMR3DECL(int) CPUMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
647{
648 RT_NOREF(pVM, enmWhat);
649 return VINF_SUCCESS;
650}
651
652
653/**
654 * Called when the ring-0 init phases completed.
655 *
656 * @param pVM The cross context VM structure.
657 */
658VMMR3DECL(void) CPUMR3LogCpuIdAndMsrFeatures(PVM pVM)
659{
660 /*
661 * Enable log buffering as we're going to log a lot of lines.
662 */
663 bool const fOldBuffered = RTLogRelSetBuffering(true /*fBuffered*/);
664
665 /*
666 * Log the cpuid.
667 */
668 RTCPUSET OnlineSet;
669 LogRel(("CPUM: Logical host processors: %u present, %u max, %u online, online mask: %016RX64\n",
670 (unsigned)RTMpGetPresentCount(), (unsigned)RTMpGetCount(), (unsigned)RTMpGetOnlineCount(),
671 RTCpuSetToU64(RTMpGetOnlineSet(&OnlineSet)) ));
672 RTCPUID cCores = RTMpGetCoreCount();
673 if (cCores)
674 LogRel(("CPUM: Physical host cores: %u\n", (unsigned)cCores));
675 RT_NOREF(pVM);
676#if 0 /** @todo Someting similar. */
677 LogRel(("************************* CPUID dump ************************\n"));
678 DBGFR3Info(pVM->pUVM, "cpuid", "verbose", DBGFR3InfoLogRelHlp());
679 LogRel(("\n"));
680 DBGFR3_INFO_LOG_SAFE(pVM, "cpuid", "verbose"); /* macro */
681 LogRel(("******************** End of CPUID dump **********************\n"));
682#endif
683
684 /*
685 * Restore the log buffering state to what it was previously.
686 */
687 RTLogRelSetBuffering(fOldBuffered);
688}
689
690
691/**
692 * Marks the guest debug state as active.
693 *
694 * @param pVCpu The cross context virtual CPU structure.
695 *
696 * @note This is used solely by NEM (hence the name) to set the correct flags here
697 * without loading the host's DRx registers, which is not possible from ring-3 anyway.
698 * The specific NEM backends have to make sure to load the correct values.
699 */
700VMMR3_INT_DECL(void) CPUMR3NemActivateGuestDebugState(PVMCPUCC pVCpu)
701{
702 ASMAtomicAndU32(&pVCpu->cpum.s.fUseFlags, ~CPUM_USED_DEBUG_REGS_HYPER);
703 ASMAtomicOrU32(&pVCpu->cpum.s.fUseFlags, CPUM_USED_DEBUG_REGS_GUEST);
704}
705
706
707/**
708 * Marks the hyper debug state as active.
709 *
710 * @param pVCpu The cross context virtual CPU structure.
711 *
712 * @note This is used solely by NEM (hence the name) to set the correct flags here
713 * without loading the host's debug registers, which is not possible from ring-3 anyway.
714 * The specific NEM backends have to make sure to load the correct values.
715 */
716VMMR3_INT_DECL(void) CPUMR3NemActivateHyperDebugState(PVMCPUCC pVCpu)
717{
718 ASMAtomicAndU32(&pVCpu->cpum.s.fUseFlags, ~CPUM_USED_DEBUG_REGS_GUEST);
719 ASMAtomicOrU32(&pVCpu->cpum.s.fUseFlags, CPUM_USED_DEBUG_REGS_HYPER);
720}
Note: See TracBrowser for help on using the repository browser.

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