VirtualBox

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

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

VMM/ARMv8: Add ability to insert new system register ranges (based on the MSR machinery from x86/amd64), bugref:10387

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