VirtualBox

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

Last change on this file since 99051 was 99051, checked in by vboxsync, 21 months ago

VMM: More ARMv8 x86/amd64 separation work, VBoxVMMArm compiles and links now, bugref:10385

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