summaryrefslogtreecommitdiff
path: root/src/VBox/VMM/VMMR3/PGM.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/VMM/VMMR3/PGM.cpp')
-rw-r--r--src/VBox/VMM/VMMR3/PGM.cpp332
1 files changed, 146 insertions, 186 deletions
diff --git a/src/VBox/VMM/VMMR3/PGM.cpp b/src/VBox/VMM/VMMR3/PGM.cpp
index b0487c62..126a06d1 100644
--- a/src/VBox/VMM/VMMR3/PGM.cpp
+++ b/src/VBox/VMM/VMMR3/PGM.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -81,6 +81,12 @@
* code to do the work. All memory use for those page tables is located below
* 4GB (this includes page tables for guest context mappings).
*
+ * Note! The intermediate memory context is also used for 64-bit guest
+ * execution on 32-bit hosts. Because we need to load 64-bit registers
+ * prior to switching to guest context, we need to be in 64-bit mode
+ * first. So, HM has some 64-bit worker routines in VMMRC.rc that get
+ * invoked via the special world switcher code in LegacyToAMD64.asm.
+ *
*
* @subsection subsec_pgm_int_gc Guest Context Mappings
*
@@ -621,9 +627,10 @@
#endif
#include <VBox/vmm/selm.h>
#include <VBox/vmm/ssm.h>
-#include <VBox/vmm/hwaccm.h>
+#include <VBox/vmm/hm.h>
#include "PGMInternal.h"
#include <VBox/vmm/vm.h>
+#include <VBox/vmm/uvm.h>
#include "PGMInline.h"
#include <VBox/dbg.h>
@@ -652,22 +659,20 @@ static DECLCALLBACK(int) pgmR3RelocatePhysHandler(PAVLROGCPHYSNODECORE pNode, v
static DECLCALLBACK(int) pgmR3RelocateVirtHandler(PAVLROGCPTRNODECORE pNode, void *pvUser);
static DECLCALLBACK(int) pgmR3RelocateHyperVirtHandler(PAVLROGCPTRNODECORE pNode, void *pvUser);
#ifdef VBOX_STRICT
-static DECLCALLBACK(void) pgmR3ResetNoMorePhysWritesFlag(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser);
+static FNVMATSTATE pgmR3ResetNoMorePhysWritesFlag;
#endif
static int pgmR3ModeDataInit(PVM pVM, bool fResolveGCAndR0);
static void pgmR3ModeDataSwitch(PVM pVM, PVMCPU pVCpu, PGMMODE enmShw, PGMMODE enmGst);
static PGMMODE pgmR3CalcShadowMode(PVM pVM, PGMMODE enmGuestMode, SUPPAGINGMODE enmHostMode, PGMMODE enmShadowMode, VMMSWITCHER *penmSwitcher);
#ifdef VBOX_WITH_DEBUGGER
-/** @todo Convert the first two commands to 'info' items. */
-static DECLCALLBACK(int) pgmR3CmdRam(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs);
-static DECLCALLBACK(int) pgmR3CmdError(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs);
-static DECLCALLBACK(int) pgmR3CmdSync(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs);
-static DECLCALLBACK(int) pgmR3CmdSyncAlways(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs);
+static FNDBGCCMD pgmR3CmdError;
+static FNDBGCCMD pgmR3CmdSync;
+static FNDBGCCMD pgmR3CmdSyncAlways;
# ifdef VBOX_STRICT
-static DECLCALLBACK(int) pgmR3CmdAssertCR3(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs);
+static FNDBGCCMD pgmR3CmdAssertCR3;
# endif
-static DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs);
+static FNDBGCCMD pgmR3CmdPhysToFile;
#endif
@@ -702,7 +707,6 @@ static const DBGCVARDESC g_aPgmCountPhysWritesArgs[] =
static const DBGCCMD g_aCmds[] =
{
/* pszCmd, cArgsMin, cArgsMax, paArgDesc, cArgDescs, fFlags, pfnHandler pszSyntax, ....pszDescription */
- { "pgmram", 0, 0, NULL, 0, 0, pgmR3CmdRam, "", "Display the ram ranges." },
{ "pgmsync", 0, 0, NULL, 0, 0, pgmR3CmdSync, "", "Sync the CR3 page." },
{ "pgmerror", 0, 1, &g_aPgmErrorArgs[0], 1, 0, pgmR3CmdError, "", "Enables inject runtime of errors into parts of PGM." },
{ "pgmerroroff", 0, 1, &g_aPgmErrorArgs[0], 1, 0, pgmR3CmdError, "", "Disables inject runtime errors into parts of PGM." },
@@ -1227,9 +1231,6 @@ VMMR3DECL(int) PGMR3Init(PVM pVM)
/*
* Init the structure.
*/
-#ifdef PGM_WITHOUT_MAPPINGS
- pVM->pgm.s.fMappingsDisabled = true;
-#endif
pVM->pgm.s.offVM = RT_OFFSETOF(VM, pgm.s);
pVM->pgm.s.offVCpuPGM = RT_OFFSETOF(VMCPU, pgm.s);
@@ -1368,7 +1369,7 @@ VMMR3DECL(int) PGMR3Init(PVM pVM)
* Register callbacks, string formatters and the saved state data unit.
*/
#ifdef VBOX_STRICT
- VMR3AtStateRegister(pVM, pgmR3ResetNoMorePhysWritesFlag, NULL);
+ VMR3AtStateRegister(pVM->pUVM, pgmR3ResetNoMorePhysWritesFlag, NULL);
#endif
PGMRegisterStringFormatTypes();
@@ -1890,6 +1891,8 @@ static int pgmR3InitStats(PVM pVM)
PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSyncHndObs, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncObsHnd", "Profiling of the Trap0eHandler body when the cause is an obsolete handler page.");
PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2SyncPT, "/PGM/CPU%u/RZ/Trap0e/Time2/SyncPT", "Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT.");
PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2WPEmulation, "/PGM/CPU%u/RZ/Trap0e/Time2/WPEmulation", "Profiling of the Trap0eHandler body when the cause is CR0.WP emulation.");
+ PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2Wp0RoUsHack, "/PGM/CPU%u/RZ/Trap0e/Time2/WP0R0USHack", "Profiling of the Trap0eHandler body when the cause is CR0.WP and netware hack to be enabled.");
+ PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2Wp0RoUsUnhack, "/PGM/CPU%u/RZ/Trap0e/Time2/WP0R0USUnhack", "Profiling of the Trap0eHandler body when the cause is CR0.WP and netware hack to be disabled.");
PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eConflicts, "/PGM/CPU%u/RZ/Trap0e/Conflicts", "The number of times #PF was caused by an undetected conflict.");
PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersMapping, "/PGM/CPU%u/RZ/Trap0e/Handlers/Mapping", "Number of traps due to access handlers in mappings.");
PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersOutOfSync, "/PGM/CPU%u/RZ/Trap0e/Handlers/OutOfSync", "Number of traps due to out-of-sync handled pages.");
@@ -2164,6 +2167,7 @@ VMMR3DECL(int) PGMR3InitFinalize(PVM pVM)
pVM->pgm.s.HCPhysInvMmioPg |= UINT64_C(0x000f0000000000);
}
+ /** @todo query from CPUM. */
pVM->pgm.s.GCPhysInvAddrMask = 0;
for (uint32_t iBit = cMaxPhysAddrWidth; iBit < 64; iBit++)
pVM->pgm.s.GCPhysInvAddrMask |= RT_BIT_64(iBit);
@@ -2238,13 +2242,13 @@ VMMR3_INT_DECL(int) PGMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
{
switch (enmWhat)
{
- case VMINITCOMPLETED_HWACCM:
+ case VMINITCOMPLETED_HM:
#ifdef VBOX_WITH_PCI_PASSTHROUGH
if (pVM->pgm.s.fPciPassthrough)
{
AssertLogRelReturn(pVM->pgm.s.fRamPreAlloc, VERR_PCI_PASSTHROUGH_NO_RAM_PREALLOC);
- AssertLogRelReturn(HWACCMIsEnabled(pVM), VERR_PCI_PASSTHROUGH_NO_HWACCM);
- AssertLogRelReturn(HWACCMIsNestedPagingActive(pVM), VERR_PCI_PASSTHROUGH_NO_NESTED_PAGING);
+ AssertLogRelReturn(HMIsEnabled(pVM), VERR_PCI_PASSTHROUGH_NO_HM);
+ AssertLogRelReturn(HMIsNestedPagingActive(pVM), VERR_PCI_PASSTHROUGH_NO_NESTED_PAGING);
/*
* Report assignments to the IOMMU (hope that's good enough for now).
@@ -2376,7 +2380,7 @@ VMMR3DECL(void) PGMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
*/
pVM->pgm.s.pvZeroPgR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pvZeroPgR3);
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
- AssertRelease(pVM->pgm.s.pvZeroPgR0 != NIL_RTR0PTR || !VMMIsHwVirtExtForced(pVM));
+ AssertRelease(pVM->pgm.s.pvZeroPgR0 != NIL_RTR0PTR || !HMIsEnabled(pVM));
#else
AssertRelease(pVM->pgm.s.pvZeroPgR0 != NIL_RTR0PTR);
#endif
@@ -2470,7 +2474,7 @@ static DECLCALLBACK(int) pgmR3RelocateHyperVirtHandler(PAVLROGCPTRNODECORE pNode
* @param pVM Pointer to the VM.
* @param pVCpu Pointer to the VMCPU.
*/
-VMMR3DECL(void) PGMR3ResetUnpluggedCpu(PVM pVM, PVMCPU pVCpu)
+VMMR3DECL(void) PGMR3ResetCpu(PVM pVM, PVMCPU pVCpu)
{
int rc = PGM_GST_PFN(Exit, pVCpu)(pVCpu);
AssertRC(rc);
@@ -2504,10 +2508,8 @@ VMMR3DECL(void) PGMR3ResetUnpluggedCpu(PVM pVM, PVMCPU pVCpu)
*
* @param pVM Pointer to the VM.
*/
-VMMR3DECL(void) PGMR3Reset(PVM pVM)
+VMMR3_INT_DECL(void) PGMR3Reset(PVM pVM)
{
- int rc;
-
LogFlow(("PGMR3Reset:\n"));
VM_ASSERT_EMT(pVM);
@@ -2528,13 +2530,13 @@ VMMR3DECL(void) PGMR3Reset(PVM pVM)
for (VMCPUID i = 0; i < pVM->cCpus; i++)
{
PVMCPU pVCpu = &pVM->aCpus[i];
- rc = PGM_GST_PFN(Exit, pVCpu)(pVCpu);
- AssertRC(rc);
+ int rc = PGM_GST_PFN(Exit, pVCpu)(pVCpu);
+ AssertReleaseRC(rc);
}
#ifdef DEBUG
- DBGFR3InfoLog(pVM, "mappings", NULL);
- DBGFR3InfoLog(pVM, "handlers", "all nostat");
+ DBGFR3_INFO_LOG(pVM, "mappings", NULL);
+ DBGFR3_INFO_LOG(pVM, "handlers", "all nostat");
#endif
/*
@@ -2544,8 +2546,8 @@ VMMR3DECL(void) PGMR3Reset(PVM pVM)
{
PVMCPU pVCpu = &pVM->aCpus[i];
- rc = PGMR3ChangeMode(pVM, pVCpu, PGMMODE_REAL);
- AssertRC(rc);
+ int rc = PGMR3ChangeMode(pVM, pVCpu, PGMMODE_REAL);
+ AssertReleaseRC(rc);
STAM_REL_COUNTER_RESET(&pVCpu->pgm.s.cGuestModeChanges);
STAM_REL_COUNTER_RESET(&pVCpu->pgm.s.cA20Changes);
@@ -2577,21 +2579,36 @@ VMMR3DECL(void) PGMR3Reset(PVM pVM)
pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
pgmR3RefreshShadowModeAfterA20Change(pVCpu);
- HWACCMFlushTLB(pVCpu);
+ HMFlushTLB(pVCpu);
#endif
}
}
- /*
- * Reset (zero) RAM and shadow ROM pages.
- */
- rc = pgmR3PhysRamReset(pVM);
- if (RT_SUCCESS(rc))
- rc = pgmR3PhysRomReset(pVM);
+ pgmUnlock(pVM);
+}
- pgmUnlock(pVM);
- AssertReleaseRC(rc);
+/**
+ * Memory setup after VM construction or reset.
+ *
+ * @param pVM Pointer to the VM.
+ * @param fAtReset Indicates the context, after reset if @c true or after
+ * construction if @c false.
+ */
+VMMR3_INT_DECL(void) PGMR3MemSetup(PVM pVM, bool fAtReset)
+{
+ if (fAtReset)
+ {
+ pgmLock(pVM);
+
+ int rc = pgmR3PhysRamZeroAll(pVM);
+ AssertReleaseRC(rc);
+
+ rc = pgmR3PhysRomReset(pVM);
+ AssertReleaseRC(rc);
+
+ pgmUnlock(pVM);
+ }
}
@@ -2600,11 +2617,11 @@ VMMR3DECL(void) PGMR3Reset(PVM pVM)
* VM state change callback for clearing fNoMorePhysWrites after
* a snapshot has been created.
*/
-static DECLCALLBACK(void) pgmR3ResetNoMorePhysWritesFlag(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser)
+static DECLCALLBACK(void) pgmR3ResetNoMorePhysWritesFlag(PUVM pUVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser)
{
if ( enmState == VMSTATE_RUNNING
|| enmState == VMSTATE_RESUMING)
- pVM->pgm.s.fNoMorePhysWrites = false;
+ pUVM->pVM->pgm.s.fNoMorePhysWrites = false;
NOREF(enmOldState); NOREF(pvUser);
}
#endif
@@ -2719,6 +2736,7 @@ static DECLCALLBACK(void) pgmR3PhysInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char
pCur->pszDesc);
}
+
/**
* Dump the page directory to the log.
*
@@ -3172,7 +3190,7 @@ static PGMMODE pgmR3CalcShadowMode(PVM pVM, PGMMODE enmGuestMode, SUPPAGINGMODE
case PGMMODE_REAL:
case PGMMODE_PROTECTED:
if ( enmShadowMode != PGMMODE_INVALID
- && !HWACCMIsEnabled(pVM) /* always switch in hwaccm mode! */)
+ && !HMIsEnabled(pVM) /* always switch in hm mode! */)
break; /* (no change) */
switch (enmHostMode)
@@ -3327,9 +3345,9 @@ static PGMMODE pgmR3CalcShadowMode(PVM pVM, PGMMODE enmGuestMode, SUPPAGINGMODE
return PGMMODE_INVALID;
}
/* Override the shadow mode is nested paging is active. */
- pVM->pgm.s.fNestedPaging = HWACCMIsNestedPagingActive(pVM);
+ pVM->pgm.s.fNestedPaging = HMIsNestedPagingActive(pVM);
if (pVM->pgm.s.fNestedPaging)
- enmShadowMode = HWACCMGetShwPagingMode(pVM);
+ enmShadowMode = HMGetShwPagingMode(pVM);
*penmSwitcher = enmSwitcher;
return enmShadowMode;
@@ -3366,7 +3384,8 @@ VMMR3DECL(int) PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode)
enmShadowMode = pgmR3CalcShadowMode(pVM, enmGuestMode, pVM->pgm.s.enmHostMode, pVCpu->pgm.s.enmShadowMode, &enmSwitcher);
#ifdef VBOX_WITH_RAW_MODE
- if (enmSwitcher != VMMSWITCHER_INVALID)
+ if ( enmSwitcher != VMMSWITCHER_INVALID
+ && !HMIsEnabled(pVM))
{
/*
* Select new switcher.
@@ -3561,7 +3580,7 @@ VMMR3DECL(int) PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode)
CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
if (!(u32Features & X86_CPUID_FEATURE_EDX_PAE))
return VMSetRuntimeError(pVM, VMSETRTERR_FLAGS_FATAL, "PAEmode",
- N_("The guest is trying to switch to the PAE mode which is currently disabled by default in VirtualBox. PAE support can be enabled using the VM settings (General/Advanced)"));
+ N_("The guest is trying to switch to the PAE mode which is currently disabled by default in VirtualBox. PAE support can be enabled using the VM settings (System/Processor)"));
GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_PAE_PAGE_MASK;
rc = PGM_GST_NAME_PAE(Enter)(pVCpu, GCPhysCR3);
@@ -3628,8 +3647,8 @@ VMMR3DECL(int) PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode)
rc = VINF_SUCCESS;
}
- /* Notify HWACCM as well. */
- HWACCMR3PagingModeChanged(pVM, pVCpu, pVCpu->pgm.s.enmShadowMode, pVCpu->pgm.s.enmGuestMode);
+ /* Notify HM as well. */
+ HMR3PagingModeChanged(pVM, pVCpu, pVCpu->pgm.s.enmShadowMode, pVCpu->pgm.s.enmGuestMode);
return rc;
}
@@ -3665,7 +3684,7 @@ int pgmR3ReEnterShadowModeAfterPoolFlush(PVM pVM, PVMCPU pVCpu)
{
pVCpu->pgm.s.enmShadowMode = PGMMODE_INVALID;
int rc = PGMR3ChangeMode(pVM, pVCpu, PGMGetGuestMode(pVCpu));
- Assert(VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
+ Assert(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
AssertRCReturn(rc, rc);
AssertRCSuccessReturn(rc, VERR_IPE_UNEXPECTED_INFO_STATUS);
@@ -3695,75 +3714,27 @@ void pgmR3RefreshShadowModeAfterA20Change(PVMCPU pVCpu)
#ifdef VBOX_WITH_DEBUGGER
/**
- * The '.pgmram' command.
- *
- * @returns VBox status.
- * @param pCmd Pointer to the command descriptor (as registered).
- * @param pCmdHlp Pointer to command helper functions.
- * @param pVM Pointer to the current VM (if any).
- * @param paArgs Pointer to (readonly) array of arguments.
- * @param cArgs Number of arguments in the array.
+ * @callback_method_impl{FNDBGCCMD, The '.pgmerror' and '.pgmerroroff' commands.}
*/
-static DECLCALLBACK(int) pgmR3CmdRam(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs)
+static DECLCALLBACK(int) pgmR3CmdError(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
{
/*
* Validate input.
*/
- NOREF(pCmd); NOREF(paArgs); NOREF(cArgs);
- if (!pVM)
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
- if (!pVM->pgm.s.pRamRangesXR3)
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Sorry, no Ram is registered.\n");
-
- /*
- * Dump the ranges.
- */
- int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "From - To (incl) pvHC\n");
- PPGMRAMRANGE pRam;
- for (pRam = pVM->pgm.s.pRamRangesXR3; pRam; pRam = pRam->pNextR3)
- {
- rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL,
- "%RGp - %RGp %p\n",
- pRam->GCPhys, pRam->GCPhysLast, pRam->pvR3);
- if (RT_FAILURE(rc))
- return rc;
- }
-
- return VINF_SUCCESS;
-}
-
-
-/**
- * The '.pgmerror' and '.pgmerroroff' commands.
- *
- * @returns VBox status.
- * @param pCmd Pointer to the command descriptor (as registered).
- * @param pCmdHlp Pointer to command helper functions.
- * @param pVM Pointer to the current VM (if any).
- * @param paArgs Pointer to (readonly) array of arguments.
- * @param cArgs Number of arguments in the array.
- */
-static DECLCALLBACK(int) pgmR3CmdError(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs)
-{
- /*
- * Validate input.
- */
- if (!pVM)
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
- AssertReturn(cArgs == 0 || (cArgs == 1 && paArgs[0].enmType == DBGCVAR_TYPE_STRING),
- pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Hit bug in the parser.\n"));
+ DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
+ PVM pVM = pUVM->pVM;
+ DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, cArgs == 0 || (cArgs == 1 && paArgs[0].enmType == DBGCVAR_TYPE_STRING));
if (!cArgs)
{
/*
* Print the list of error injection locations with status.
*/
- pCmdHlp->pfnPrintf(pCmdHlp, NULL, "PGM error inject locations:\n");
- pCmdHlp->pfnPrintf(pCmdHlp, NULL, " handy - %RTbool\n", pVM->pgm.s.fErrInjHandyPages);
+ DBGCCmdHlpPrintf(pCmdHlp, "PGM error inject locations:\n");
+ DBGCCmdHlpPrintf(pCmdHlp, " handy - %RTbool\n", pVM->pgm.s.fErrInjHandyPages);
}
else
{
-
/*
* String switch on where to inject the error.
*/
@@ -3772,150 +3743,138 @@ static DECLCALLBACK(int) pgmR3CmdError(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM
if (!strcmp(pszWhere, "handy"))
ASMAtomicWriteBool(&pVM->pgm.s.fErrInjHandyPages, fNewState);
else
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid 'where' value: %s.\n", pszWhere);
- pCmdHlp->pfnPrintf(pCmdHlp, NULL, "done\n");
+ return DBGCCmdHlpPrintf(pCmdHlp, "error: Invalid 'where' value: %s.\n", pszWhere);
+ DBGCCmdHlpPrintf(pCmdHlp, "done\n");
}
return VINF_SUCCESS;
}
/**
- * The '.pgmsync' command.
- *
- * @returns VBox status.
- * @param pCmd Pointer to the command descriptor (as registered).
- * @param pCmdHlp Pointer to command helper functions.
- * @param pVM Pointer to the current VM (if any).
- * @param paArgs Pointer to (readonly) array of arguments.
- * @param cArgs Number of arguments in the array.
+ * @callback_method_impl{FNDBGCCMD, The '.pgmsync' command.}
*/
-static DECLCALLBACK(int) pgmR3CmdSync(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs)
+static DECLCALLBACK(int) pgmR3CmdSync(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
{
- /** @todo SMP support */
-
/*
* Validate input.
*/
NOREF(pCmd); NOREF(paArgs); NOREF(cArgs);
- if (!pVM)
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
-
- PVMCPU pVCpu = &pVM->aCpus[0];
+ DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
+ PVMCPU pVCpu = VMMR3GetCpuByIdU(pUVM, DBGCCmdHlpGetCurrentCpu(pCmdHlp));
+ if (!pVCpu)
+ return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid CPU ID");
/*
* Force page directory sync.
*/
VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
- int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Forcing page directory sync.\n");
+ int rc = DBGCCmdHlpPrintf(pCmdHlp, "Forcing page directory sync.\n");
if (RT_FAILURE(rc))
return rc;
return VINF_SUCCESS;
}
-
#ifdef VBOX_STRICT
+
/**
- * The '.pgmassertcr3' command.
- *
- * @returns VBox status.
- * @param pCmd Pointer to the command descriptor (as registered).
- * @param pCmdHlp Pointer to command helper functions.
- * @param pVM Pointer to the current VM (if any).
- * @param paArgs Pointer to (readonly) array of arguments.
- * @param cArgs Number of arguments in the array.
+ * EMT callback for pgmR3CmdAssertCR3.
+ *
+ * @returns VBox status code.
+ * @param pUVM The user mode VM handle.
+ * @param pcErrors Where to return the error count.
*/
-static DECLCALLBACK(int) pgmR3CmdAssertCR3(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs)
+static DECLCALLBACK(int) pgmR3CmdAssertCR3EmtWorker(PUVM pUVM, unsigned *pcErrors)
{
- /** @todo SMP support!! */
+ PVM pVM = pUVM->pVM;
+ VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
+ PVMCPU pVCpu = VMMGetCpu(pVM);
+
+ *pcErrors = PGMAssertCR3(pVM, pVCpu, CPUMGetGuestCR3(pVCpu), CPUMGetGuestCR4(pVCpu));
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * @callback_method_impl{FNDBGCCMD, The '.pgmassertcr3' command.}
+ */
+static DECLCALLBACK(int) pgmR3CmdAssertCR3(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
+{
/*
* Validate input.
*/
NOREF(pCmd); NOREF(paArgs); NOREF(cArgs);
- if (!pVM)
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
-
- PVMCPU pVCpu = &pVM->aCpus[0];
+ DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
- int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Checking shadow CR3 page tables for consistency.\n");
+ int rc = DBGCCmdHlpPrintf(pCmdHlp, "Checking shadow CR3 page tables for consistency.\n");
if (RT_FAILURE(rc))
return rc;
- PGMAssertCR3(pVM, pVCpu, CPUMGetGuestCR3(pVCpu), CPUMGetGuestCR4(pVCpu));
-
- return VINF_SUCCESS;
+ unsigned cErrors = 0;
+ rc = VMR3ReqCallWaitU(pUVM, DBGCCmdHlpGetCurrentCpu(pCmdHlp), (PFNRT)pgmR3CmdAssertCR3EmtWorker, 2, pUVM, &cErrors);
+ if (RT_FAILURE(rc))
+ return DBGCCmdHlpFail(pCmdHlp, pCmd, "VMR3ReqCallWaitU failed: %Rrc", rc);
+ if (cErrors > 0)
+ return DBGCCmdHlpFail(pCmdHlp, pCmd, "PGMAssertCR3: %u error(s)", cErrors);
+ return DBGCCmdHlpPrintf(pCmdHlp, "PGMAssertCR3: OK\n");
}
-#endif /* VBOX_STRICT */
+#endif /* VBOX_STRICT */
/**
- * The '.pgmsyncalways' command.
- *
- * @returns VBox status.
- * @param pCmd Pointer to the command descriptor (as registered).
- * @param pCmdHlp Pointer to command helper functions.
- * @param pVM Pointer to the current VM (if any).
- * @param paArgs Pointer to (readonly) array of arguments.
- * @param cArgs Number of arguments in the array.
+ * @callback_method_impl{FNDBGCCMD, The '.pgmsyncalways' command.}
*/
-static DECLCALLBACK(int) pgmR3CmdSyncAlways(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs)
+static DECLCALLBACK(int) pgmR3CmdSyncAlways(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
{
- /** @todo SMP support!! */
- PVMCPU pVCpu = &pVM->aCpus[0];
-
/*
* Validate input.
*/
NOREF(pCmd); NOREF(paArgs); NOREF(cArgs);
- if (!pVM)
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
+ DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
+ PVMCPU pVCpu = VMMR3GetCpuByIdU(pUVM, DBGCCmdHlpGetCurrentCpu(pCmdHlp));
+ if (!pVCpu)
+ return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid CPU ID");
/*
* Force page directory sync.
*/
+ int rc;
if (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_ALWAYS)
{
ASMAtomicAndU32(&pVCpu->pgm.s.fSyncFlags, ~PGM_SYNC_ALWAYS);
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Disabled permanent forced page directory syncing.\n");
+ rc = DBGCCmdHlpPrintf(pCmdHlp, "Disabled permanent forced page directory syncing.\n");
}
else
{
ASMAtomicOrU32(&pVCpu->pgm.s.fSyncFlags, PGM_SYNC_ALWAYS);
VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Enabled permanent forced page directory syncing.\n");
+ rc = DBGCCmdHlpPrintf(pCmdHlp, "Enabled permanent forced page directory syncing.\n");
}
+ return rc;
}
/**
- * The '.pgmphystofile' command.
- *
- * @returns VBox status.
- * @param pCmd Pointer to the command descriptor (as registered).
- * @param pCmdHlp Pointer to command helper functions.
- * @param pVM Pointer to the current VM (if any).
- * @param paArgs Pointer to (readonly) array of arguments.
- * @param cArgs Number of arguments in the array.
+ * @callback_method_impl{FNDBGCCMD, The '.pgmphystofile' command.}
*/
-static DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs)
+static DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
{
/*
* Validate input.
*/
NOREF(pCmd);
- if (!pVM)
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
- if ( cArgs < 1
- || cArgs > 2
- || paArgs[0].enmType != DBGCVAR_TYPE_STRING
- || ( cArgs > 1
- && paArgs[1].enmType != DBGCVAR_TYPE_STRING))
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: parser error, invalid arguments.\n");
- if ( cArgs >= 2
- && strcmp(paArgs[1].u.pszString, "nozero"))
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid 2nd argument '%s', must be 'nozero'.\n", paArgs[1].u.pszString);
+ DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
+ PVM pVM = pUVM->pVM;
+ DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, cArgs == 1 || cArgs == 2);
+ DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, paArgs[0].enmType != DBGCVAR_TYPE_STRING);
+ if (cArgs == 2)
+ {
+ DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 1, paArgs[2].enmType != DBGCVAR_TYPE_STRING);
+ if (strcmp(paArgs[1].u.pszString, "nozero"))
+ return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid 2nd argument '%s', must be 'nozero'.\n", paArgs[1].u.pszString);
+ }
bool fIncZeroPgs = cArgs < 2;
/*
@@ -3924,12 +3883,12 @@ static DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp,
RTFILE hFile;
int rc = RTFileOpen(&hFile, paArgs[0].u.pszString, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE);
if (RT_FAILURE(rc))
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: RTFileOpen(,'%s',) -> %Rrc.\n", paArgs[0].u.pszString, rc);
+ return DBGCCmdHlpPrintf(pCmdHlp, "error: RTFileOpen(,'%s',) -> %Rrc.\n", paArgs[0].u.pszString, rc);
uint32_t cbRamHole = 0;
- CFGMR3QueryU32Def(CFGMR3GetRoot(pVM), "RamHoleSize", &cbRamHole, MM_RAM_HOLE_SIZE_DEFAULT);
+ CFGMR3QueryU32Def(CFGMR3GetRootU(pUVM), "RamHoleSize", &cbRamHole, MM_RAM_HOLE_SIZE_DEFAULT);
uint64_t cbRam = 0;
- CFGMR3QueryU64Def(CFGMR3GetRoot(pVM), "RamSize", &cbRam, 0);
+ CFGMR3QueryU64Def(CFGMR3GetRootU(pUVM), "RamSize", &cbRam, 0);
RTGCPHYS GCPhysEnd = cbRam + cbRamHole;
/*
@@ -3964,7 +3923,7 @@ static DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp,
{
rc = RTFileWrite(hFile, abZeroPg, PAGE_SIZE, NULL);
if (RT_FAILURE(rc))
- pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
+ DBGCCmdHlpPrintf(pCmdHlp, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
}
}
else
@@ -3984,22 +3943,23 @@ static DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp,
rc = RTFileWrite(hFile, pvPage, PAGE_SIZE, NULL);
PGMPhysReleasePageMappingLock(pVM, &Lock);
if (RT_FAILURE(rc))
- pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
+ DBGCCmdHlpPrintf(pCmdHlp, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
}
else
- pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: PGMPhysGCPhys2CCPtrReadOnly -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
+ DBGCCmdHlpPrintf(pCmdHlp, "error: PGMPhysGCPhys2CCPtrReadOnly -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
break;
}
default:
AssertFailed();
- case PGMPAGETYPE_MMIO2_ALIAS_MMIO:
case PGMPAGETYPE_MMIO:
+ case PGMPAGETYPE_MMIO2_ALIAS_MMIO:
+ case PGMPAGETYPE_SPECIAL_ALIAS_MMIO:
if (fIncZeroPgs)
{
rc = RTFileWrite(hFile, abZeroPg, PAGE_SIZE, NULL);
if (RT_FAILURE(rc))
- pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
+ DBGCCmdHlpPrintf(pCmdHlp, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
}
break;
}
@@ -4015,7 +3975,7 @@ static DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp,
RTFileClose(hFile);
if (RT_SUCCESS(rc))
- return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Successfully saved physical memory to '%s'.\n", paArgs[0].u.pszString);
+ return DBGCCmdHlpPrintf(pCmdHlp, "Successfully saved physical memory to '%s'.\n", paArgs[0].u.pszString);
return VINF_SUCCESS;
}