VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/PGM-armv8.cpp@ 102468

Last change on this file since 102468 was 100759, checked in by vboxsync, 17 months ago

VMM/PGM-armv8: Make it work with saved states, bugref:10388

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.5 KB
Line 
1/* $Id: PGM-armv8.cpp 100759 2023-07-31 14:33:14Z vboxsync $ */
2/** @file
3 * PGM - Page Manager and Monitor, ARMv8 variant. (Mixing stuff here, not good?)
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
29/** @page pg_pgm_armv8 PGM - The Page Manager and Monitor (ARMv8 variant)
30 *
31 * For now this is just a stub for bringing up the ARMv8 hypervisor. We'll see how
32 * much we really need here later on and whether it makes sense to merge this with the original PGM.cpp
33 * (avoiding \#ifdef hell for with this as I'm not confident enough to fiddle around with PGM too much at this point).
34 */
35
36
37/*********************************************************************************************************************************
38* Header Files *
39*********************************************************************************************************************************/
40#define LOG_GROUP LOG_GROUP_PGM
41#define VBOX_WITHOUT_PAGING_BIT_FIELDS /* 64-bit bitfields are just asking for trouble. See @bugref{9841} and others. */
42#include <VBox/vmm/dbgf.h>
43#include <VBox/vmm/pgm.h>
44#include <VBox/vmm/cpum.h>
45#include <VBox/vmm/iom.h>
46#include <VBox/sup.h>
47#include <VBox/vmm/mm.h>
48#include <VBox/vmm/em.h>
49#include <VBox/vmm/stam.h>
50#include <VBox/vmm/selm.h>
51#include <VBox/vmm/ssm.h>
52#include <VBox/vmm/hm.h>
53#include "PGMInternal.h"
54#include <VBox/vmm/vmcc.h>
55#include <VBox/vmm/uvm.h>
56#include "PGMInline.h"
57
58#include <VBox/dbg.h>
59#include <VBox/param.h>
60#include <VBox/err.h>
61
62#include <iprt/asm.h>
63#include <iprt/assert.h>
64#include <iprt/env.h>
65#include <iprt/file.h>
66#include <iprt/mem.h>
67#include <iprt/rand.h>
68#include <iprt/string.h>
69#include <iprt/thread.h>
70
71
72/*********************************************************************************************************************************
73* Structures and Typedefs *
74*********************************************************************************************************************************/
75
76
77/*********************************************************************************************************************************
78* Internal Functions *
79*********************************************************************************************************************************/
80#ifdef VBOX_STRICT
81static FNVMATSTATE pgmR3ResetNoMorePhysWritesFlag;
82#endif
83
84
85/*********************************************************************************************************************************
86* Global Variables *
87*********************************************************************************************************************************/
88#ifndef VBOX_WITH_PGM_NEM_MODE
89# error "This requires VBOX_WITH_PGM_NEM_MODE to be set at all times!"
90#endif
91
92/**
93 * Interface that NEM uses to switch PGM into simplified memory managment mode.
94 *
95 * This call occurs before PGMR3Init.
96 *
97 * @param pVM The cross context VM structure.
98 */
99VMMR3_INT_DECL(void) PGMR3EnableNemMode(PVM pVM)
100{
101 AssertFatal(!PDMCritSectIsInitialized(&pVM->pgm.s.CritSectX));
102 pVM->pgm.s.fNemMode = true;
103}
104
105
106/**
107 * Checks whether the simplificed memory management mode for NEM is enabled.
108 *
109 * @returns true if enabled, false if not.
110 * @param pVM The cross context VM structure.
111 */
112VMMR3_INT_DECL(bool) PGMR3IsNemModeEnabled(PVM pVM)
113{
114 return pVM->pgm.s.fNemMode;
115}
116
117
118/**
119 * Initiates the paging of VM.
120 *
121 * @returns VBox status code.
122 * @param pVM The cross context VM structure.
123 */
124VMMR3DECL(int) PGMR3Init(PVM pVM)
125{
126 LogFlow(("PGMR3Init:\n"));
127 PCFGMNODE pCfgPGM = CFGMR3GetChild(CFGMR3GetRoot(pVM), "/PGM");
128 int rc;
129
130 /*
131 * Assert alignment and sizes.
132 */
133 AssertCompile(sizeof(pVM->pgm.s) <= sizeof(pVM->pgm.padding));
134 AssertCompile(sizeof(pVM->apCpusR3[0]->pgm.s) <= sizeof(pVM->apCpusR3[0]->pgm.padding));
135 AssertCompileMemberAlignment(PGM, CritSectX, sizeof(uintptr_t));
136
137 /*
138 * If we're in driveless mode we have to use the simplified memory mode.
139 */
140 bool const fDriverless = SUPR3IsDriverless();
141 AssertReturn(fDriverless, VERR_NOT_SUPPORTED);
142 if (!pVM->pgm.s.fNemMode)
143 pVM->pgm.s.fNemMode = true;
144
145 /*
146 * Init the structure.
147 */
148 /*pVM->pgm.s.fRestoreRomPagesAtReset = false;*/
149
150 for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
151 {
152 pVM->pgm.s.aHandyPages[i].HCPhysGCPhys = NIL_GMMPAGEDESC_PHYS;
153 pVM->pgm.s.aHandyPages[i].fZeroed = false;
154 pVM->pgm.s.aHandyPages[i].idPage = NIL_GMM_PAGEID;
155 pVM->pgm.s.aHandyPages[i].idSharedPage = NIL_GMM_PAGEID;
156 }
157
158 for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.aLargeHandyPage); i++)
159 {
160 pVM->pgm.s.aLargeHandyPage[i].HCPhysGCPhys = NIL_GMMPAGEDESC_PHYS;
161 pVM->pgm.s.aLargeHandyPage[i].fZeroed = false;
162 pVM->pgm.s.aLargeHandyPage[i].idPage = NIL_GMM_PAGEID;
163 pVM->pgm.s.aLargeHandyPage[i].idSharedPage = NIL_GMM_PAGEID;
164 }
165
166 AssertReleaseReturn(pVM->pgm.s.cPhysHandlerTypes == 0, VERR_WRONG_ORDER);
167 for (size_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aPhysHandlerTypes); i++)
168 {
169 if (fDriverless)
170 pVM->pgm.s.aPhysHandlerTypes[i].hType = i | (RTRandU64() & ~(uint64_t)PGMPHYSHANDLERTYPE_IDX_MASK);
171 pVM->pgm.s.aPhysHandlerTypes[i].enmKind = PGMPHYSHANDLERKIND_INVALID;
172 pVM->pgm.s.aPhysHandlerTypes[i].pfnHandler = pgmR3HandlerPhysicalHandlerInvalid;
173 }
174
175#if 0
176 /* Init the per-CPU part. */
177 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
178 {
179 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
180 PPGMCPU pPGM = &pVCpu->pgm.s;
181 }
182#endif
183
184 rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "RamPreAlloc", &pVM->pgm.s.fRamPreAlloc,
185#ifdef VBOX_WITH_PREALLOC_RAM_BY_DEFAULT
186 true
187#else
188 false
189#endif
190 );
191 AssertLogRelRCReturn(rc, rc);
192
193 rc = CFGMR3QueryU32Def(pCfgPGM, "MaxRing3Chunks", &pVM->pgm.s.ChunkR3Map.cMax, UINT32_MAX);
194 AssertLogRelRCReturn(rc, rc);
195 for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.ChunkR3Map.Tlb.aEntries); i++)
196 pVM->pgm.s.ChunkR3Map.Tlb.aEntries[i].idChunk = NIL_GMM_CHUNKID;
197
198 /*
199 * Get the configured RAM size - to estimate saved state size.
200 */
201 uint64_t cbRam;
202 rc = CFGMR3QueryU64(CFGMR3GetRoot(pVM), "RamSize", &cbRam);
203 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
204 cbRam = 0;
205 else if (RT_SUCCESS(rc))
206 {
207 if (cbRam < GUEST_PAGE_SIZE)
208 cbRam = 0;
209 cbRam = RT_ALIGN_64(cbRam, GUEST_PAGE_SIZE);
210 }
211 else
212 {
213 AssertMsgFailed(("Configuration error: Failed to query integer \"RamSize\", rc=%Rrc.\n", rc));
214 return rc;
215 }
216
217 /** @cfgm{/PGM/ZeroRamPagesOnReset, boolean, true}
218 * Whether to clear RAM pages on (hard) reset. */
219 rc = CFGMR3QueryBoolDef(pCfgPGM, "ZeroRamPagesOnReset", &pVM->pgm.s.fZeroRamPagesOnReset, true);
220 AssertLogRelRCReturn(rc, rc);
221
222 /*
223 * Register callbacks, string formatters and the saved state data unit.
224 */
225#ifdef VBOX_STRICT
226 VMR3AtStateRegister(pVM->pUVM, pgmR3ResetNoMorePhysWritesFlag, NULL);
227#endif
228 PGMRegisterStringFormatTypes();
229
230 rc = pgmR3InitSavedState(pVM, cbRam);
231 if (RT_FAILURE(rc))
232 return rc;
233
234 /*
235 * Initialize the PGM critical section and flush the phys TLBs
236 */
237 rc = PDMR3CritSectInit(pVM, &pVM->pgm.s.CritSectX, RT_SRC_POS, "PGM");
238 AssertRCReturn(rc, rc);
239
240 PGMR3PhysChunkInvalidateTLB(pVM);
241 pgmPhysInvalidatePageMapTLB(pVM);
242
243 /*
244 * For the time being we sport a full set of handy pages in addition to the base
245 * memory to simplify things.
246 */
247 rc = MMR3ReserveHandyPages(pVM, RT_ELEMENTS(pVM->pgm.s.aHandyPages)); /** @todo this should be changed to PGM_HANDY_PAGES_MIN but this needs proper testing... */
248 AssertRCReturn(rc, rc);
249
250 /*
251 * Setup the zero page (HCPHysZeroPg is set by ring-0).
252 */
253 RT_ZERO(pVM->pgm.s.abZeroPg); /* paranoia */
254 if (fDriverless)
255 pVM->pgm.s.HCPhysZeroPg = _4G - GUEST_PAGE_SIZE * 2 /* fake to avoid PGM_PAGE_INIT_ZERO assertion */;
256 AssertRelease(pVM->pgm.s.HCPhysZeroPg != NIL_RTHCPHYS);
257 AssertRelease(pVM->pgm.s.HCPhysZeroPg != 0);
258
259 /*
260 * Setup the invalid MMIO page (HCPhysMmioPg is set by ring-0).
261 * (The invalid bits in HCPhysInvMmioPg are set later on init complete.)
262 */
263 ASMMemFill32(pVM->pgm.s.abMmioPg, sizeof(pVM->pgm.s.abMmioPg), 0xfeedface);
264 if (fDriverless)
265 pVM->pgm.s.HCPhysMmioPg = _4G - GUEST_PAGE_SIZE * 3 /* fake to avoid PGM_PAGE_INIT_ZERO assertion */;
266 AssertRelease(pVM->pgm.s.HCPhysMmioPg != NIL_RTHCPHYS);
267 AssertRelease(pVM->pgm.s.HCPhysMmioPg != 0);
268 pVM->pgm.s.HCPhysInvMmioPg = pVM->pgm.s.HCPhysMmioPg;
269
270 /*
271 * Initialize physical access handlers.
272 */
273 /** @cfgm{/PGM/MaxPhysicalAccessHandlers, uint32_t, 32, 65536, 6144}
274 * Number of physical access handlers allowed (subject to rounding). This is
275 * managed as one time allocation during initializations. The default is
276 * lower for a driverless setup. */
277 /** @todo can lower it for nested paging too, at least when there is no
278 * nested guest involved. */
279 uint32_t cAccessHandlers = 0;
280 rc = CFGMR3QueryU32Def(pCfgPGM, "MaxPhysicalAccessHandlers", &cAccessHandlers, !fDriverless ? 6144 : 640);
281 AssertLogRelRCReturn(rc, rc);
282 AssertLogRelMsgStmt(cAccessHandlers >= 32, ("cAccessHandlers=%#x, min 32\n", cAccessHandlers), cAccessHandlers = 32);
283 AssertLogRelMsgStmt(cAccessHandlers <= _64K, ("cAccessHandlers=%#x, max 65536\n", cAccessHandlers), cAccessHandlers = _64K);
284 if (!fDriverless)
285 {
286 rc = VMMR3CallR0(pVM, VMMR0_DO_PGM_PHYS_HANDLER_INIT, cAccessHandlers, NULL);
287 AssertRCReturn(rc, rc);
288 AssertPtr(pVM->pgm.s.pPhysHandlerTree);
289 AssertPtr(pVM->pgm.s.PhysHandlerAllocator.m_paNodes);
290 AssertPtr(pVM->pgm.s.PhysHandlerAllocator.m_pbmAlloc);
291 }
292 else
293 {
294 uint32_t cbTreeAndBitmap = 0;
295 uint32_t const cbTotalAligned = pgmHandlerPhysicalCalcTableSizes(&cAccessHandlers, &cbTreeAndBitmap);
296 uint8_t *pb = NULL;
297 rc = SUPR3PageAlloc(cbTotalAligned >> HOST_PAGE_SHIFT, 0, (void **)&pb);
298 AssertLogRelRCReturn(rc, rc);
299
300 pVM->pgm.s.PhysHandlerAllocator.initSlabAllocator(cAccessHandlers, (PPGMPHYSHANDLER)&pb[cbTreeAndBitmap],
301 (uint64_t *)&pb[sizeof(PGMPHYSHANDLERTREE)]);
302 pVM->pgm.s.pPhysHandlerTree = (PPGMPHYSHANDLERTREE)pb;
303 pVM->pgm.s.pPhysHandlerTree->initWithAllocator(&pVM->pgm.s.PhysHandlerAllocator);
304 }
305
306 /*
307 * Register the physical access handler protecting ROMs.
308 */
309 if (RT_SUCCESS(rc))
310 /** @todo why isn't pgmPhysRomWriteHandler registered for ring-0? */
311 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_WRITE, 0 /*fFlags*/, pgmPhysRomWriteHandler,
312 "ROM write protection", &pVM->pgm.s.hRomPhysHandlerType);
313
314 /*
315 * Register the physical access handler doing dirty MMIO2 tracing.
316 */
317 if (RT_SUCCESS(rc))
318 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_WRITE, PGMPHYSHANDLER_F_KEEP_PGM_LOCK,
319 pgmPhysMmio2WriteHandler, "MMIO2 dirty page tracing",
320 &pVM->pgm.s.hMmio2DirtyPhysHandlerType);
321
322 if (RT_SUCCESS(rc))
323 return VINF_SUCCESS;
324
325 /* Almost no cleanup necessary, MM frees all memory. */
326 PDMR3CritSectDelete(pVM, &pVM->pgm.s.CritSectX);
327
328 return rc;
329}
330
331
332/**
333 * Ring-3 init finalizing.
334 *
335 * @returns VBox status code.
336 * @param pVM The cross context VM structure.
337 */
338VMMR3DECL(int) PGMR3InitFinalize(PVM pVM)
339{
340 /*
341 * Allocate memory if we're supposed to do that.
342 */
343 int rc = VINF_SUCCESS;
344 if (pVM->pgm.s.fRamPreAlloc)
345 rc = pgmR3PhysRamPreAllocate(pVM);
346
347 //pgmLogState(pVM);
348 LogRel(("PGM: PGMR3InitFinalize: 4 MB PSE mask %RGp -> %Rrc\n", pVM->pgm.s.GCPhys4MBPSEMask, rc));
349 return rc;
350}
351
352
353/**
354 * Init phase completed callback.
355 *
356 * @returns VBox status code.
357 * @param pVM The cross context VM structure.
358 * @param enmWhat What has been completed.
359 * @thread EMT(0)
360 */
361VMMR3_INT_DECL(int) PGMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
362{
363 switch (enmWhat)
364 {
365 case VMINITCOMPLETED_HM:
366 AssertLogRelReturn(!pVM->pgm.s.fPciPassthrough, VERR_PGM_PCI_PASSTHRU_MISCONFIG);
367 break;
368
369 default:
370 /* shut up gcc */
371 break;
372 }
373
374 return VINF_SUCCESS;
375}
376
377
378/**
379 * Applies relocations to data and code managed by this component.
380 *
381 * This function will be called at init and whenever the VMM need to relocate it
382 * self inside the GC.
383 *
384 * @param pVM The cross context VM structure.
385 * @param offDelta Relocation delta relative to old location.
386 */
387VMMR3DECL(void) PGMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
388{
389 LogFlow(("PGMR3Relocate: offDelta=%RGv\n", offDelta));
390 RT_NOREF(pVM, offDelta);
391}
392
393
394/**
395 * Resets a virtual CPU when unplugged.
396 *
397 * @param pVM The cross context VM structure.
398 * @param pVCpu The cross context virtual CPU structure.
399 */
400VMMR3DECL(void) PGMR3ResetCpu(PVM pVM, PVMCPU pVCpu)
401{
402 RT_NOREF(pVM, pVCpu);
403}
404
405
406/**
407 * The VM is being reset.
408 *
409 * For the PGM component this means that any PD write monitors
410 * needs to be removed.
411 *
412 * @param pVM The cross context VM structure.
413 */
414VMMR3_INT_DECL(void) PGMR3Reset(PVM pVM)
415{
416 LogFlow(("PGMR3Reset:\n"));
417 VM_ASSERT_EMT(pVM);
418
419 PGM_LOCK_VOID(pVM);
420
421#ifdef DEBUG
422 DBGFR3_INFO_LOG_SAFE(pVM, "mappings", NULL);
423 DBGFR3_INFO_LOG_SAFE(pVM, "handlers", "all nostat");
424#endif
425
426 //pgmLogState(pVM);
427 PGM_UNLOCK(pVM);
428}
429
430
431/**
432 * Memory setup after VM construction or reset.
433 *
434 * @param pVM The cross context VM structure.
435 * @param fAtReset Indicates the context, after reset if @c true or after
436 * construction if @c false.
437 */
438VMMR3_INT_DECL(void) PGMR3MemSetup(PVM pVM, bool fAtReset)
439{
440 if (fAtReset)
441 {
442 PGM_LOCK_VOID(pVM);
443
444 int rc = pgmR3PhysRamZeroAll(pVM);
445 AssertReleaseRC(rc);
446
447 rc = pgmR3PhysRomReset(pVM);
448 AssertReleaseRC(rc);
449
450 PGM_UNLOCK(pVM);
451 }
452}
453
454
455#ifdef VBOX_STRICT
456/**
457 * VM state change callback for clearing fNoMorePhysWrites after
458 * a snapshot has been created.
459 */
460static DECLCALLBACK(void) pgmR3ResetNoMorePhysWritesFlag(PUVM pUVM, PCVMMR3VTABLE pVMM, VMSTATE enmState,
461 VMSTATE enmOldState, void *pvUser)
462{
463 if ( enmState == VMSTATE_RUNNING
464 || enmState == VMSTATE_RESUMING)
465 pUVM->pVM->pgm.s.fNoMorePhysWrites = false;
466 RT_NOREF(pVMM, enmOldState, pvUser);
467}
468#endif
469
470/**
471 * Private API to reset fNoMorePhysWrites.
472 */
473VMMR3_INT_DECL(void) PGMR3ResetNoMorePhysWritesFlag(PVM pVM)
474{
475 pVM->pgm.s.fNoMorePhysWrites = false;
476}
477
478/**
479 * Terminates the PGM.
480 *
481 * @returns VBox status code.
482 * @param pVM The cross context VM structure.
483 */
484VMMR3DECL(int) PGMR3Term(PVM pVM)
485{
486 /* Must free shared pages here. */
487 PGM_LOCK_VOID(pVM);
488 pgmR3PhysRamTerm(pVM);
489 pgmR3PhysRomTerm(pVM);
490 PGM_UNLOCK(pVM);
491
492 PGMDeregisterStringFormatTypes();
493 return PDMR3CritSectDelete(pVM, &pVM->pgm.s.CritSectX);
494}
495
496
497/**
498 * Perform an integrity check on the PGM component.
499 *
500 * @returns VINF_SUCCESS if everything is fine.
501 * @returns VBox error status after asserting on integrity breach.
502 * @param pVM The cross context VM structure.
503 */
504VMMR3DECL(int) PGMR3CheckIntegrity(PVM pVM)
505{
506 RT_NOREF(pVM);
507 return VINF_SUCCESS;
508}
509
510
511VMMDECL(bool) PGMHasDirtyPages(PVM pVM)
512{
513 return pVM->pgm.s.CTX_SUFF(pPool)->cDirtyPages != 0;
514}
515
516
517VMMDECL(bool) PGMIsLockOwner(PVMCC pVM)
518{
519 return PDMCritSectIsOwner(pVM, &pVM->pgm.s.CritSectX);
520}
521
522
523VMMDECL(int) PGMSetLargePageUsage(PVMCC pVM, bool fUseLargePages)
524{
525 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
526
527 pVM->pgm.s.fUseLargePages = fUseLargePages;
528 return VINF_SUCCESS;
529}
530
531
532#if defined(VBOX_STRICT) || defined(DOXYGEN_RUNNING)
533int pgmLockDebug(PVMCC pVM, bool fVoid, RT_SRC_POS_DECL)
534#else
535int pgmLock(PVMCC pVM, bool fVoid)
536#endif
537{
538#if defined(VBOX_STRICT)
539 int rc = PDMCritSectEnterDebug(pVM, &pVM->pgm.s.CritSectX, VINF_SUCCESS, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
540#else
541 int rc = PDMCritSectEnter(pVM, &pVM->pgm.s.CritSectX, VINF_SUCCESS);
542#endif
543 if (RT_SUCCESS(rc))
544 return rc;
545 if (fVoid)
546 PDM_CRITSECT_RELEASE_ASSERT_RC(pVM, &pVM->pgm.s.CritSectX, rc);
547 else
548 AssertRC(rc);
549 return rc;
550}
551
552
553void pgmUnlock(PVMCC pVM)
554{
555 uint32_t cDeprecatedPageLocks = pVM->pgm.s.cDeprecatedPageLocks;
556 pVM->pgm.s.cDeprecatedPageLocks = 0;
557 int rc = PDMCritSectLeave(pVM, &pVM->pgm.s.CritSectX);
558 if (rc == VINF_SEM_NESTED)
559 pVM->pgm.s.cDeprecatedPageLocks = cDeprecatedPageLocks;
560}
561
562
563#if !defined(IN_R0) || defined(LOG_ENABLED)
564
565/** Format handler for PGMPAGE.
566 * @copydoc FNRTSTRFORMATTYPE */
567static DECLCALLBACK(size_t) pgmFormatTypeHandlerPage(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
568 const char *pszType, void const *pvValue,
569 int cchWidth, int cchPrecision, unsigned fFlags,
570 void *pvUser)
571{
572 size_t cch;
573 PCPGMPAGE pPage = (PCPGMPAGE)pvValue;
574 if (RT_VALID_PTR(pPage))
575 {
576 char szTmp[64+80];
577
578 cch = 0;
579
580 /* The single char state stuff. */
581 static const char s_achPageStates[4] = { 'Z', 'A', 'W', 'S' };
582 szTmp[cch++] = s_achPageStates[PGM_PAGE_GET_STATE_NA(pPage)];
583
584# define IS_PART_INCLUDED(lvl) ( !(fFlags & RTSTR_F_PRECISION) || cchPrecision == (lvl) || cchPrecision >= (lvl)+10 )
585 if (IS_PART_INCLUDED(5))
586 {
587 static const char s_achHandlerStates[4*2] = { '-', 't', 'w', 'a' , '_', 'T', 'W', 'A' };
588 szTmp[cch++] = s_achHandlerStates[ PGM_PAGE_GET_HNDL_PHYS_STATE(pPage)
589 | ((uint8_t)PGM_PAGE_IS_HNDL_PHYS_NOT_IN_HM(pPage) << 2)];
590 }
591
592 /* The type. */
593 if (IS_PART_INCLUDED(4))
594 {
595 szTmp[cch++] = ':';
596 static const char s_achPageTypes[8][4] = { "INV", "RAM", "MI2", "M2A", "SHA", "ROM", "MIO", "BAD" };
597 szTmp[cch++] = s_achPageTypes[PGM_PAGE_GET_TYPE_NA(pPage)][0];
598 szTmp[cch++] = s_achPageTypes[PGM_PAGE_GET_TYPE_NA(pPage)][1];
599 szTmp[cch++] = s_achPageTypes[PGM_PAGE_GET_TYPE_NA(pPage)][2];
600 }
601
602 /* The numbers. */
603 if (IS_PART_INCLUDED(3))
604 {
605 szTmp[cch++] = ':';
606 cch += RTStrFormatNumber(&szTmp[cch], PGM_PAGE_GET_HCPHYS_NA(pPage), 16, 12, 0, RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
607 }
608
609 if (IS_PART_INCLUDED(2))
610 {
611 szTmp[cch++] = ':';
612 cch += RTStrFormatNumber(&szTmp[cch], PGM_PAGE_GET_PAGEID(pPage), 16, 7, 0, RTSTR_F_ZEROPAD | RTSTR_F_32BIT);
613 }
614
615 if (IS_PART_INCLUDED(6))
616 {
617 szTmp[cch++] = ':';
618 static const char s_achRefs[4] = { '-', 'U', '!', 'L' };
619 szTmp[cch++] = s_achRefs[PGM_PAGE_GET_TD_CREFS_NA(pPage)];
620 cch += RTStrFormatNumber(&szTmp[cch], PGM_PAGE_GET_TD_IDX_NA(pPage), 16, 4, 0, RTSTR_F_ZEROPAD | RTSTR_F_16BIT);
621 }
622# undef IS_PART_INCLUDED
623
624 cch = pfnOutput(pvArgOutput, szTmp, cch);
625 }
626 else
627 cch = pfnOutput(pvArgOutput, RT_STR_TUPLE("<bad-pgmpage-ptr>"));
628 NOREF(pszType); NOREF(cchWidth); NOREF(pvUser);
629 return cch;
630}
631
632
633/** Format handler for PGMRAMRANGE.
634 * @copydoc FNRTSTRFORMATTYPE */
635static DECLCALLBACK(size_t) pgmFormatTypeHandlerRamRange(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
636 const char *pszType, void const *pvValue,
637 int cchWidth, int cchPrecision, unsigned fFlags,
638 void *pvUser)
639{
640 size_t cch;
641 PGMRAMRANGE const *pRam = (PGMRAMRANGE const *)pvValue;
642 if (RT_VALID_PTR(pRam))
643 {
644 char szTmp[80];
645 cch = RTStrPrintf(szTmp, sizeof(szTmp), "%RGp-%RGp", pRam->GCPhys, pRam->GCPhysLast);
646 cch = pfnOutput(pvArgOutput, szTmp, cch);
647 }
648 else
649 cch = pfnOutput(pvArgOutput, RT_STR_TUPLE("<bad-pgmramrange-ptr>"));
650 NOREF(pszType); NOREF(cchWidth); NOREF(cchPrecision); NOREF(pvUser); NOREF(fFlags);
651 return cch;
652}
653
654/** Format type andlers to be registered/deregistered. */
655static const struct
656{
657 char szType[24];
658 PFNRTSTRFORMATTYPE pfnHandler;
659} g_aPgmFormatTypes[] =
660{
661 { "pgmpage", pgmFormatTypeHandlerPage },
662 { "pgmramrange", pgmFormatTypeHandlerRamRange }
663};
664
665#endif /* !IN_R0 || LOG_ENABLED */
666
667
668VMMDECL(int) PGMRegisterStringFormatTypes(void)
669{
670#if !defined(IN_R0) || defined(LOG_ENABLED)
671 int rc = VINF_SUCCESS;
672 unsigned i;
673 for (i = 0; RT_SUCCESS(rc) && i < RT_ELEMENTS(g_aPgmFormatTypes); i++)
674 {
675 rc = RTStrFormatTypeRegister(g_aPgmFormatTypes[i].szType, g_aPgmFormatTypes[i].pfnHandler, NULL);
676# ifdef IN_RING0
677 if (rc == VERR_ALREADY_EXISTS)
678 {
679 /* in case of cleanup failure in ring-0 */
680 RTStrFormatTypeDeregister(g_aPgmFormatTypes[i].szType);
681 rc = RTStrFormatTypeRegister(g_aPgmFormatTypes[i].szType, g_aPgmFormatTypes[i].pfnHandler, NULL);
682 }
683# endif
684 }
685 if (RT_FAILURE(rc))
686 while (i-- > 0)
687 RTStrFormatTypeDeregister(g_aPgmFormatTypes[i].szType);
688
689 return rc;
690#else
691 return VINF_SUCCESS;
692#endif
693}
694
695
696VMMDECL(void) PGMDeregisterStringFormatTypes(void)
697{
698#if !defined(IN_R0) || defined(LOG_ENABLED)
699 for (unsigned i = 0; i < RT_ELEMENTS(g_aPgmFormatTypes); i++)
700 RTStrFormatTypeDeregister(g_aPgmFormatTypes[i].szType);
701#endif
702}
703
704
705VMMDECL(int) PGMGstModifyPage(PVMCPUCC pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
706{
707 STAM_PROFILE_START(&pVCpu->pgm.s.Stats.CTX_MID_Z(Stat,GstModifyPage), a);
708 VMCPU_ASSERT_EMT(pVCpu);
709
710 /*
711 * Validate input.
712 */
713 Assert(cb);
714
715 LogFlow(("PGMGstModifyPage %RGv %d bytes fFlags=%08llx fMask=%08llx\n", GCPtr, cb, fFlags, fMask));
716 RT_NOREF(pVCpu, GCPtr, cb, fFlags, fMask);
717
718 AssertReleaseFailed();
719 return VERR_NOT_IMPLEMENTED;
720}
721
722
723VMMDECL(PGMMODE) PGMGetGuestMode(PVMCPU pVCpu)
724{
725 return pVCpu->pgm.s.enmGuestMode;
726}
727
728
729VMMDECL(PGMMODE) PGMGetShadowMode(PVMCPU pVCpu)
730{
731 return pVCpu->pgm.s.enmShadowMode;
732}
733
734
735VMMDECL(int) PGMGstGetPage(PVMCPUCC pVCpu, RTGCPTR GCPtr, PPGMPTWALK pWalk)
736{
737 VMCPU_ASSERT_EMT(pVCpu);
738 Assert(pWalk);
739 AssertReleaseFailed();
740 RT_NOREF(pVCpu, GCPtr, pWalk);
741 return VERR_NOT_IMPLEMENTED;
742}
743
744
745VMMDECL(int) PGMShwMakePageReadonly(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fOpFlags)
746{
747 AssertReleaseFailed();
748 RT_NOREF(pVCpu, GCPtr, fOpFlags);
749 return VERR_NOT_IMPLEMENTED;
750}
751
752
753VMMDECL(int) PGMShwMakePageWritable(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fOpFlags)
754{
755 AssertReleaseFailed();
756 RT_NOREF(pVCpu, GCPtr, fOpFlags);
757 return VERR_NOT_IMPLEMENTED;
758}
759
760
761VMMDECL(int) PGMShwMakePageNotPresent(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fOpFlags)
762{
763 AssertReleaseFailed();
764 RT_NOREF(pVCpu, GCPtr, fOpFlags);
765 return VERR_NOT_IMPLEMENTED;
766}
767
768
769VMM_INT_DECL(int) PGMHCChangeMode(PVMCC pVM, PVMCPUCC pVCpu, PGMMODE enmGuestMode, bool fForce)
770{
771 //AssertReleaseFailed(); /** @todo Called by the PGM saved state code. */
772 RT_NOREF(pVM, pVCpu, enmGuestMode, fForce);
773 return VINF_SUCCESS;
774}
775
776
777VMMDECL(int) PGMShwGetPage(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys)
778{
779 AssertReleaseFailed();
780 RT_NOREF(pVCpu, GCPtr, pfFlags, pHCPhys);
781 return VERR_NOT_SUPPORTED;
782}
783
784
785int pgmR3ExitShadowModeBeforePoolFlush(PVMCPU pVCpu)
786{
787 RT_NOREF(pVCpu);
788 return VINF_SUCCESS;
789}
790
791
792int pgmR3ReEnterShadowModeAfterPoolFlush(PVM pVM, PVMCPU pVCpu)
793{
794 RT_NOREF(pVM, pVCpu);
795 return VINF_SUCCESS;
796}
797
798
799void pgmR3RefreshShadowModeAfterA20Change(PVMCPU pVCpu)
800{
801 RT_NOREF(pVCpu);
802}
803
804
805int pgmGstPtWalk(PVMCPUCC pVCpu, RTGCPTR GCPtr, PPGMPTWALK pWalk, PPGMPTWALKGST pGstWalk)
806{
807 VMCPU_ASSERT_EMT(pVCpu);
808 AssertReleaseFailed();
809 RT_NOREF(pVCpu, GCPtr, pWalk, pGstWalk);
810 return VERR_NOT_IMPLEMENTED;
811}
812
813
814int pgmGstPtWalkNext(PVMCPUCC pVCpu, RTGCPTR GCPtr, PPGMPTWALK pWalk, PPGMPTWALKGST pGstWalk)
815{
816 VMCPU_ASSERT_EMT(pVCpu);
817 AssertReleaseFailed();
818 RT_NOREF(pVCpu, GCPtr, pWalk, pGstWalk);
819 return VERR_NOT_IMPLEMENTED;
820}
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