VirtualBox

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

最後變更 在這個檔案從99377是 99196,由 vboxsync 提交於 2 年 前

VMM: Start on system register handling for ARMv8 (which is ver similar to how we handle MSR accesses on x86), bugref:10385

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

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