VirtualBox

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

Last change on this file since 105702 was 104885, checked in by vboxsync, 6 months ago

VMM/PGM: Lockless PGMPhysIemGCPhys2PtrNoLock. bugref:10687

  • 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 104885 2024-06-11 12:37:11Z 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, false /*fInRendezvous*/); /* includes pgmPhysInvalidatePageMapTLB call */
241
242 /*
243 * For the time being we sport a full set of handy pages in addition to the base
244 * memory to simplify things.
245 */
246 rc = MMR3ReserveHandyPages(pVM, RT_ELEMENTS(pVM->pgm.s.aHandyPages)); /** @todo this should be changed to PGM_HANDY_PAGES_MIN but this needs proper testing... */
247 AssertRCReturn(rc, rc);
248
249 /*
250 * Setup the zero page (HCPHysZeroPg is set by ring-0).
251 */
252 RT_ZERO(pVM->pgm.s.abZeroPg); /* paranoia */
253 if (fDriverless)
254 pVM->pgm.s.HCPhysZeroPg = _4G - GUEST_PAGE_SIZE * 2 /* fake to avoid PGM_PAGE_INIT_ZERO assertion */;
255 AssertRelease(pVM->pgm.s.HCPhysZeroPg != NIL_RTHCPHYS);
256 AssertRelease(pVM->pgm.s.HCPhysZeroPg != 0);
257
258 /*
259 * Setup the invalid MMIO page (HCPhysMmioPg is set by ring-0).
260 * (The invalid bits in HCPhysInvMmioPg are set later on init complete.)
261 */
262 ASMMemFill32(pVM->pgm.s.abMmioPg, sizeof(pVM->pgm.s.abMmioPg), 0xfeedface);
263 if (fDriverless)
264 pVM->pgm.s.HCPhysMmioPg = _4G - GUEST_PAGE_SIZE * 3 /* fake to avoid PGM_PAGE_INIT_ZERO assertion */;
265 AssertRelease(pVM->pgm.s.HCPhysMmioPg != NIL_RTHCPHYS);
266 AssertRelease(pVM->pgm.s.HCPhysMmioPg != 0);
267 pVM->pgm.s.HCPhysInvMmioPg = pVM->pgm.s.HCPhysMmioPg;
268
269 /*
270 * Initialize physical access handlers.
271 */
272 /** @cfgm{/PGM/MaxPhysicalAccessHandlers, uint32_t, 32, 65536, 6144}
273 * Number of physical access handlers allowed (subject to rounding). This is
274 * managed as one time allocation during initializations. The default is
275 * lower for a driverless setup. */
276 /** @todo can lower it for nested paging too, at least when there is no
277 * nested guest involved. */
278 uint32_t cAccessHandlers = 0;
279 rc = CFGMR3QueryU32Def(pCfgPGM, "MaxPhysicalAccessHandlers", &cAccessHandlers, !fDriverless ? 6144 : 640);
280 AssertLogRelRCReturn(rc, rc);
281 AssertLogRelMsgStmt(cAccessHandlers >= 32, ("cAccessHandlers=%#x, min 32\n", cAccessHandlers), cAccessHandlers = 32);
282 AssertLogRelMsgStmt(cAccessHandlers <= _64K, ("cAccessHandlers=%#x, max 65536\n", cAccessHandlers), cAccessHandlers = _64K);
283 if (!fDriverless)
284 {
285 rc = VMMR3CallR0(pVM, VMMR0_DO_PGM_PHYS_HANDLER_INIT, cAccessHandlers, NULL);
286 AssertRCReturn(rc, rc);
287 AssertPtr(pVM->pgm.s.pPhysHandlerTree);
288 AssertPtr(pVM->pgm.s.PhysHandlerAllocator.m_paNodes);
289 AssertPtr(pVM->pgm.s.PhysHandlerAllocator.m_pbmAlloc);
290 }
291 else
292 {
293 uint32_t cbTreeAndBitmap = 0;
294 uint32_t const cbTotalAligned = pgmHandlerPhysicalCalcTableSizes(&cAccessHandlers, &cbTreeAndBitmap);
295 uint8_t *pb = NULL;
296 rc = SUPR3PageAlloc(cbTotalAligned >> HOST_PAGE_SHIFT, 0, (void **)&pb);
297 AssertLogRelRCReturn(rc, rc);
298
299 pVM->pgm.s.PhysHandlerAllocator.initSlabAllocator(cAccessHandlers, (PPGMPHYSHANDLER)&pb[cbTreeAndBitmap],
300 (uint64_t *)&pb[sizeof(PGMPHYSHANDLERTREE)]);
301 pVM->pgm.s.pPhysHandlerTree = (PPGMPHYSHANDLERTREE)pb;
302 pVM->pgm.s.pPhysHandlerTree->initWithAllocator(&pVM->pgm.s.PhysHandlerAllocator);
303 }
304
305 /*
306 * Register the physical access handler protecting ROMs.
307 */
308 if (RT_SUCCESS(rc))
309 /** @todo why isn't pgmPhysRomWriteHandler registered for ring-0? */
310 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_WRITE, 0 /*fFlags*/, pgmPhysRomWriteHandler,
311 "ROM write protection", &pVM->pgm.s.hRomPhysHandlerType);
312
313 /*
314 * Register the physical access handler doing dirty MMIO2 tracing.
315 */
316 if (RT_SUCCESS(rc))
317 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_WRITE, PGMPHYSHANDLER_F_KEEP_PGM_LOCK,
318 pgmPhysMmio2WriteHandler, "MMIO2 dirty page tracing",
319 &pVM->pgm.s.hMmio2DirtyPhysHandlerType);
320
321 if (RT_SUCCESS(rc))
322 return VINF_SUCCESS;
323
324 /* Almost no cleanup necessary, MM frees all memory. */
325 PDMR3CritSectDelete(pVM, &pVM->pgm.s.CritSectX);
326
327 return rc;
328}
329
330
331/**
332 * Ring-3 init finalizing.
333 *
334 * @returns VBox status code.
335 * @param pVM The cross context VM structure.
336 */
337VMMR3DECL(int) PGMR3InitFinalize(PVM pVM)
338{
339 /*
340 * Allocate memory if we're supposed to do that.
341 */
342 int rc = VINF_SUCCESS;
343 if (pVM->pgm.s.fRamPreAlloc)
344 rc = pgmR3PhysRamPreAllocate(pVM);
345
346 //pgmLogState(pVM);
347 LogRel(("PGM: PGMR3InitFinalize: 4 MB PSE mask %RGp -> %Rrc\n", pVM->pgm.s.GCPhys4MBPSEMask, rc));
348 return rc;
349}
350
351
352/**
353 * Init phase completed callback.
354 *
355 * @returns VBox status code.
356 * @param pVM The cross context VM structure.
357 * @param enmWhat What has been completed.
358 * @thread EMT(0)
359 */
360VMMR3_INT_DECL(int) PGMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
361{
362 switch (enmWhat)
363 {
364 case VMINITCOMPLETED_HM:
365 AssertLogRelReturn(!pVM->pgm.s.fPciPassthrough, VERR_PGM_PCI_PASSTHRU_MISCONFIG);
366 break;
367
368 default:
369 /* shut up gcc */
370 break;
371 }
372
373 return VINF_SUCCESS;
374}
375
376
377/**
378 * Applies relocations to data and code managed by this component.
379 *
380 * This function will be called at init and whenever the VMM need to relocate it
381 * self inside the GC.
382 *
383 * @param pVM The cross context VM structure.
384 * @param offDelta Relocation delta relative to old location.
385 */
386VMMR3DECL(void) PGMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
387{
388 LogFlow(("PGMR3Relocate: offDelta=%RGv\n", offDelta));
389 RT_NOREF(pVM, offDelta);
390}
391
392
393/**
394 * Resets a virtual CPU when unplugged.
395 *
396 * @param pVM The cross context VM structure.
397 * @param pVCpu The cross context virtual CPU structure.
398 */
399VMMR3DECL(void) PGMR3ResetCpu(PVM pVM, PVMCPU pVCpu)
400{
401 RT_NOREF(pVM, pVCpu);
402}
403
404
405/**
406 * The VM is being reset.
407 *
408 * For the PGM component this means that any PD write monitors
409 * needs to be removed.
410 *
411 * @param pVM The cross context VM structure.
412 */
413VMMR3_INT_DECL(void) PGMR3Reset(PVM pVM)
414{
415 LogFlow(("PGMR3Reset:\n"));
416 VM_ASSERT_EMT(pVM);
417
418 PGM_LOCK_VOID(pVM);
419
420#ifdef DEBUG
421 DBGFR3_INFO_LOG_SAFE(pVM, "mappings", NULL);
422 DBGFR3_INFO_LOG_SAFE(pVM, "handlers", "all nostat");
423#endif
424
425 //pgmLogState(pVM);
426 PGM_UNLOCK(pVM);
427}
428
429
430/**
431 * Memory setup after VM construction or reset.
432 *
433 * @param pVM The cross context VM structure.
434 * @param fAtReset Indicates the context, after reset if @c true or after
435 * construction if @c false.
436 */
437VMMR3_INT_DECL(void) PGMR3MemSetup(PVM pVM, bool fAtReset)
438{
439 if (fAtReset)
440 {
441 PGM_LOCK_VOID(pVM);
442
443 int rc = pgmR3PhysRamZeroAll(pVM);
444 AssertReleaseRC(rc);
445
446 rc = pgmR3PhysRomReset(pVM);
447 AssertReleaseRC(rc);
448
449 PGM_UNLOCK(pVM);
450 }
451}
452
453
454#ifdef VBOX_STRICT
455/**
456 * VM state change callback for clearing fNoMorePhysWrites after
457 * a snapshot has been created.
458 */
459static DECLCALLBACK(void) pgmR3ResetNoMorePhysWritesFlag(PUVM pUVM, PCVMMR3VTABLE pVMM, VMSTATE enmState,
460 VMSTATE enmOldState, void *pvUser)
461{
462 if ( enmState == VMSTATE_RUNNING
463 || enmState == VMSTATE_RESUMING)
464 pUVM->pVM->pgm.s.fNoMorePhysWrites = false;
465 RT_NOREF(pVMM, enmOldState, pvUser);
466}
467#endif
468
469/**
470 * Private API to reset fNoMorePhysWrites.
471 */
472VMMR3_INT_DECL(void) PGMR3ResetNoMorePhysWritesFlag(PVM pVM)
473{
474 pVM->pgm.s.fNoMorePhysWrites = false;
475}
476
477/**
478 * Terminates the PGM.
479 *
480 * @returns VBox status code.
481 * @param pVM The cross context VM structure.
482 */
483VMMR3DECL(int) PGMR3Term(PVM pVM)
484{
485 /* Must free shared pages here. */
486 PGM_LOCK_VOID(pVM);
487 pgmR3PhysRamTerm(pVM);
488 pgmR3PhysRomTerm(pVM);
489 PGM_UNLOCK(pVM);
490
491 PGMDeregisterStringFormatTypes();
492 return PDMR3CritSectDelete(pVM, &pVM->pgm.s.CritSectX);
493}
494
495
496/**
497 * Perform an integrity check on the PGM component.
498 *
499 * @returns VINF_SUCCESS if everything is fine.
500 * @returns VBox error status after asserting on integrity breach.
501 * @param pVM The cross context VM structure.
502 */
503VMMR3DECL(int) PGMR3CheckIntegrity(PVM pVM)
504{
505 RT_NOREF(pVM);
506 return VINF_SUCCESS;
507}
508
509
510VMMDECL(bool) PGMHasDirtyPages(PVM pVM)
511{
512 return pVM->pgm.s.CTX_SUFF(pPool)->cDirtyPages != 0;
513}
514
515
516VMMDECL(bool) PGMIsLockOwner(PVMCC pVM)
517{
518 return PDMCritSectIsOwner(pVM, &pVM->pgm.s.CritSectX);
519}
520
521
522VMMDECL(int) PGMSetLargePageUsage(PVMCC pVM, bool fUseLargePages)
523{
524 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
525
526 pVM->pgm.s.fUseLargePages = fUseLargePages;
527 return VINF_SUCCESS;
528}
529
530
531#if defined(VBOX_STRICT) || defined(DOXYGEN_RUNNING)
532int pgmLockDebug(PVMCC pVM, bool fVoid, RT_SRC_POS_DECL)
533#else
534int pgmLock(PVMCC pVM, bool fVoid)
535#endif
536{
537#if defined(VBOX_STRICT)
538 int rc = PDMCritSectEnterDebug(pVM, &pVM->pgm.s.CritSectX, VINF_SUCCESS, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
539#else
540 int rc = PDMCritSectEnter(pVM, &pVM->pgm.s.CritSectX, VINF_SUCCESS);
541#endif
542 if (RT_SUCCESS(rc))
543 return rc;
544 if (fVoid)
545 PDM_CRITSECT_RELEASE_ASSERT_RC(pVM, &pVM->pgm.s.CritSectX, rc);
546 else
547 AssertRC(rc);
548 return rc;
549}
550
551
552void pgmUnlock(PVMCC pVM)
553{
554 uint32_t cDeprecatedPageLocks = pVM->pgm.s.cDeprecatedPageLocks;
555 pVM->pgm.s.cDeprecatedPageLocks = 0;
556 int rc = PDMCritSectLeave(pVM, &pVM->pgm.s.CritSectX);
557 if (rc == VINF_SEM_NESTED)
558 pVM->pgm.s.cDeprecatedPageLocks = cDeprecatedPageLocks;
559}
560
561
562#if !defined(IN_R0) || defined(LOG_ENABLED)
563
564/** Format handler for PGMPAGE.
565 * @copydoc FNRTSTRFORMATTYPE */
566static DECLCALLBACK(size_t) pgmFormatTypeHandlerPage(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
567 const char *pszType, void const *pvValue,
568 int cchWidth, int cchPrecision, unsigned fFlags,
569 void *pvUser)
570{
571 size_t cch;
572 PCPGMPAGE pPage = (PCPGMPAGE)pvValue;
573 if (RT_VALID_PTR(pPage))
574 {
575 char szTmp[64+80];
576
577 cch = 0;
578
579 /* The single char state stuff. */
580 static const char s_achPageStates[4] = { 'Z', 'A', 'W', 'S' };
581 szTmp[cch++] = s_achPageStates[PGM_PAGE_GET_STATE_NA(pPage)];
582
583# define IS_PART_INCLUDED(lvl) ( !(fFlags & RTSTR_F_PRECISION) || cchPrecision == (lvl) || cchPrecision >= (lvl)+10 )
584 if (IS_PART_INCLUDED(5))
585 {
586 static const char s_achHandlerStates[4*2] = { '-', 't', 'w', 'a' , '_', 'T', 'W', 'A' };
587 szTmp[cch++] = s_achHandlerStates[ PGM_PAGE_GET_HNDL_PHYS_STATE(pPage)
588 | ((uint8_t)PGM_PAGE_IS_HNDL_PHYS_NOT_IN_HM(pPage) << 2)];
589 }
590
591 /* The type. */
592 if (IS_PART_INCLUDED(4))
593 {
594 szTmp[cch++] = ':';
595 static const char s_achPageTypes[8][4] = { "INV", "RAM", "MI2", "M2A", "SHA", "ROM", "MIO", "BAD" };
596 szTmp[cch++] = s_achPageTypes[PGM_PAGE_GET_TYPE_NA(pPage)][0];
597 szTmp[cch++] = s_achPageTypes[PGM_PAGE_GET_TYPE_NA(pPage)][1];
598 szTmp[cch++] = s_achPageTypes[PGM_PAGE_GET_TYPE_NA(pPage)][2];
599 }
600
601 /* The numbers. */
602 if (IS_PART_INCLUDED(3))
603 {
604 szTmp[cch++] = ':';
605 cch += RTStrFormatNumber(&szTmp[cch], PGM_PAGE_GET_HCPHYS_NA(pPage), 16, 12, 0, RTSTR_F_ZEROPAD | RTSTR_F_64BIT);
606 }
607
608 if (IS_PART_INCLUDED(2))
609 {
610 szTmp[cch++] = ':';
611 cch += RTStrFormatNumber(&szTmp[cch], PGM_PAGE_GET_PAGEID(pPage), 16, 7, 0, RTSTR_F_ZEROPAD | RTSTR_F_32BIT);
612 }
613
614 if (IS_PART_INCLUDED(6))
615 {
616 szTmp[cch++] = ':';
617 static const char s_achRefs[4] = { '-', 'U', '!', 'L' };
618 szTmp[cch++] = s_achRefs[PGM_PAGE_GET_TD_CREFS_NA(pPage)];
619 cch += RTStrFormatNumber(&szTmp[cch], PGM_PAGE_GET_TD_IDX_NA(pPage), 16, 4, 0, RTSTR_F_ZEROPAD | RTSTR_F_16BIT);
620 }
621# undef IS_PART_INCLUDED
622
623 cch = pfnOutput(pvArgOutput, szTmp, cch);
624 }
625 else
626 cch = pfnOutput(pvArgOutput, RT_STR_TUPLE("<bad-pgmpage-ptr>"));
627 NOREF(pszType); NOREF(cchWidth); NOREF(pvUser);
628 return cch;
629}
630
631
632/** Format handler for PGMRAMRANGE.
633 * @copydoc FNRTSTRFORMATTYPE */
634static DECLCALLBACK(size_t) pgmFormatTypeHandlerRamRange(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
635 const char *pszType, void const *pvValue,
636 int cchWidth, int cchPrecision, unsigned fFlags,
637 void *pvUser)
638{
639 size_t cch;
640 PGMRAMRANGE const *pRam = (PGMRAMRANGE const *)pvValue;
641 if (RT_VALID_PTR(pRam))
642 {
643 char szTmp[80];
644 cch = RTStrPrintf(szTmp, sizeof(szTmp), "%RGp-%RGp", pRam->GCPhys, pRam->GCPhysLast);
645 cch = pfnOutput(pvArgOutput, szTmp, cch);
646 }
647 else
648 cch = pfnOutput(pvArgOutput, RT_STR_TUPLE("<bad-pgmramrange-ptr>"));
649 NOREF(pszType); NOREF(cchWidth); NOREF(cchPrecision); NOREF(pvUser); NOREF(fFlags);
650 return cch;
651}
652
653/** Format type andlers to be registered/deregistered. */
654static const struct
655{
656 char szType[24];
657 PFNRTSTRFORMATTYPE pfnHandler;
658} g_aPgmFormatTypes[] =
659{
660 { "pgmpage", pgmFormatTypeHandlerPage },
661 { "pgmramrange", pgmFormatTypeHandlerRamRange }
662};
663
664#endif /* !IN_R0 || LOG_ENABLED */
665
666
667VMMDECL(int) PGMRegisterStringFormatTypes(void)
668{
669#if !defined(IN_R0) || defined(LOG_ENABLED)
670 int rc = VINF_SUCCESS;
671 unsigned i;
672 for (i = 0; RT_SUCCESS(rc) && i < RT_ELEMENTS(g_aPgmFormatTypes); i++)
673 {
674 rc = RTStrFormatTypeRegister(g_aPgmFormatTypes[i].szType, g_aPgmFormatTypes[i].pfnHandler, NULL);
675# ifdef IN_RING0
676 if (rc == VERR_ALREADY_EXISTS)
677 {
678 /* in case of cleanup failure in ring-0 */
679 RTStrFormatTypeDeregister(g_aPgmFormatTypes[i].szType);
680 rc = RTStrFormatTypeRegister(g_aPgmFormatTypes[i].szType, g_aPgmFormatTypes[i].pfnHandler, NULL);
681 }
682# endif
683 }
684 if (RT_FAILURE(rc))
685 while (i-- > 0)
686 RTStrFormatTypeDeregister(g_aPgmFormatTypes[i].szType);
687
688 return rc;
689#else
690 return VINF_SUCCESS;
691#endif
692}
693
694
695VMMDECL(void) PGMDeregisterStringFormatTypes(void)
696{
697#if !defined(IN_R0) || defined(LOG_ENABLED)
698 for (unsigned i = 0; i < RT_ELEMENTS(g_aPgmFormatTypes); i++)
699 RTStrFormatTypeDeregister(g_aPgmFormatTypes[i].szType);
700#endif
701}
702
703
704VMMDECL(int) PGMGstModifyPage(PVMCPUCC pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
705{
706 STAM_PROFILE_START(&pVCpu->pgm.s.Stats.CTX_MID_Z(Stat,GstModifyPage), a);
707 VMCPU_ASSERT_EMT(pVCpu);
708
709 /*
710 * Validate input.
711 */
712 Assert(cb);
713
714 LogFlow(("PGMGstModifyPage %RGv %d bytes fFlags=%08llx fMask=%08llx\n", GCPtr, cb, fFlags, fMask));
715 RT_NOREF(pVCpu, GCPtr, cb, fFlags, fMask);
716
717 AssertReleaseFailed();
718 return VERR_NOT_IMPLEMENTED;
719}
720
721
722VMMDECL(PGMMODE) PGMGetGuestMode(PVMCPU pVCpu)
723{
724 return pVCpu->pgm.s.enmGuestMode;
725}
726
727
728VMMDECL(PGMMODE) PGMGetShadowMode(PVMCPU pVCpu)
729{
730 return pVCpu->pgm.s.enmShadowMode;
731}
732
733
734VMMDECL(int) PGMGstGetPage(PVMCPUCC pVCpu, RTGCPTR GCPtr, PPGMPTWALK pWalk)
735{
736 VMCPU_ASSERT_EMT(pVCpu);
737 Assert(pWalk);
738 AssertReleaseFailed();
739 RT_NOREF(pVCpu, GCPtr, pWalk);
740 return VERR_NOT_IMPLEMENTED;
741}
742
743
744VMMDECL(int) PGMShwMakePageReadonly(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fOpFlags)
745{
746 AssertReleaseFailed();
747 RT_NOREF(pVCpu, GCPtr, fOpFlags);
748 return VERR_NOT_IMPLEMENTED;
749}
750
751
752VMMDECL(int) PGMShwMakePageWritable(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fOpFlags)
753{
754 AssertReleaseFailed();
755 RT_NOREF(pVCpu, GCPtr, fOpFlags);
756 return VERR_NOT_IMPLEMENTED;
757}
758
759
760VMMDECL(int) PGMShwMakePageNotPresent(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fOpFlags)
761{
762 AssertReleaseFailed();
763 RT_NOREF(pVCpu, GCPtr, fOpFlags);
764 return VERR_NOT_IMPLEMENTED;
765}
766
767
768VMM_INT_DECL(int) PGMHCChangeMode(PVMCC pVM, PVMCPUCC pVCpu, PGMMODE enmGuestMode, bool fForce)
769{
770 //AssertReleaseFailed(); /** @todo Called by the PGM saved state code. */
771 RT_NOREF(pVM, pVCpu, enmGuestMode, fForce);
772 return VINF_SUCCESS;
773}
774
775
776VMMDECL(int) PGMShwGetPage(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys)
777{
778 AssertReleaseFailed();
779 RT_NOREF(pVCpu, GCPtr, pfFlags, pHCPhys);
780 return VERR_NOT_SUPPORTED;
781}
782
783
784int pgmR3ExitShadowModeBeforePoolFlush(PVMCPU pVCpu)
785{
786 RT_NOREF(pVCpu);
787 return VINF_SUCCESS;
788}
789
790
791int pgmR3ReEnterShadowModeAfterPoolFlush(PVM pVM, PVMCPU pVCpu)
792{
793 RT_NOREF(pVM, pVCpu);
794 return VINF_SUCCESS;
795}
796
797
798void pgmR3RefreshShadowModeAfterA20Change(PVMCPU pVCpu)
799{
800 RT_NOREF(pVCpu);
801}
802
803
804int pgmGstPtWalk(PVMCPUCC pVCpu, RTGCPTR GCPtr, PPGMPTWALK pWalk, PPGMPTWALKGST pGstWalk)
805{
806 VMCPU_ASSERT_EMT(pVCpu);
807 AssertReleaseFailed();
808 RT_NOREF(pVCpu, GCPtr, pWalk, pGstWalk);
809 return VERR_NOT_IMPLEMENTED;
810}
811
812
813int pgmGstPtWalkNext(PVMCPUCC pVCpu, RTGCPTR GCPtr, PPGMPTWALK pWalk, PPGMPTWALKGST pGstWalk)
814{
815 VMCPU_ASSERT_EMT(pVCpu);
816 AssertReleaseFailed();
817 RT_NOREF(pVCpu, GCPtr, pWalk, pGstWalk);
818 return VERR_NOT_IMPLEMENTED;
819}
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