summaryrefslogtreecommitdiff
path: root/src/VBox/VMM/VMMR3/CSAM.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/VMM/VMMR3/CSAM.cpp')
-rw-r--r--src/VBox/VMM/VMMR3/CSAM.cpp263
1 files changed, 171 insertions, 92 deletions
diff --git a/src/VBox/VMM/VMMR3/CSAM.cpp b/src/VBox/VMM/VMMR3/CSAM.cpp
index 5946b9e2..86cce499 100644
--- a/src/VBox/VMM/VMMR3/CSAM.cpp
+++ b/src/VBox/VMM/VMMR3/CSAM.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2012 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;
@@ -26,29 +26,33 @@
#include <VBox/vmm/cpumdis.h>
#include <VBox/vmm/pgm.h>
#include <VBox/vmm/iom.h>
-#include <VBox/sup.h>
#include <VBox/vmm/mm.h>
#include <VBox/vmm/em.h>
+#include <VBox/vmm/hm.h>
#ifdef VBOX_WITH_REM
# include <VBox/vmm/rem.h>
#endif
#include <VBox/vmm/selm.h>
#include <VBox/vmm/trpm.h>
#include <VBox/vmm/cfgm.h>
+#include <VBox/vmm/ssm.h>
#include <VBox/param.h>
#include <iprt/avl.h>
#include <iprt/asm.h>
#include <iprt/thread.h>
#include "CSAMInternal.h"
#include <VBox/vmm/vm.h>
+#include <VBox/vmm/uvm.h>
+
#include <VBox/dbg.h>
+#include <VBox/sup.h>
#include <VBox/err.h>
-#include <VBox/vmm/ssm.h>
#include <VBox/log.h>
-#include <iprt/assert.h>
-#include <iprt/string.h>
+
#include <VBox/dis.h>
#include <VBox/disopcode.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
#include "internal/pgm.h"
@@ -82,13 +86,16 @@ static int csamAnalyseCodeStream(PVM pVM, RCPTRTYPE(uint8_t *) pInstrGC
/** @todo Temporary for debugging. */
static bool fInCSAMCodePageInvalidate = false;
+#ifdef VBOX_WITH_DEBUGGER
+static FNDBGCCMD csamr3CmdOn;
+static FNDBGCCMD csamr3CmdOff;
+#endif
+
+
/*******************************************************************************
* Global Variables *
*******************************************************************************/
#ifdef VBOX_WITH_DEBUGGER
-static DECLCALLBACK(int) csamr3CmdOn(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs);
-static DECLCALLBACK(int) csamr3CmdOff(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs);
-
/** Command descriptors. */
static const DBGCCMD g_aCmds[] =
{
@@ -213,10 +220,22 @@ static const SSMFIELD g_aCsamPageRecFields[] =
* @returns VBox status code.
* @param pVM Pointer to the VM.
*/
-VMMR3DECL(int) CSAMR3Init(PVM pVM)
+VMMR3_INT_DECL(int) CSAMR3Init(PVM pVM)
{
int rc;
+ /*
+ * We only need a saved state dummy loader if HM is enabled.
+ */
+ if (HMIsEnabled(pVM))
+ {
+ pVM->fCSAMEnabled = false;
+ return SSMR3RegisterStub(pVM, "CSAM", 0);
+ }
+
+ /*
+ * Raw-mode.
+ */
LogFlow(("CSAMR3Init\n"));
/* Allocate bitmap for the page directory. */
@@ -324,6 +343,7 @@ static int csamReinit(PVM pVM)
*/
AssertRelease(!(RT_OFFSETOF(VM, csam.s) & 31));
AssertRelease(sizeof(pVM->csam.s) <= sizeof(pVM->csam.padding));
+ AssertRelease(!HMIsEnabled(pVM));
/*
* Setup any fixed pointers and offsets.
@@ -361,9 +381,9 @@ static int csamReinit(PVM pVM)
* @param pVM The VM.
* @param offDelta Relocation delta.
*/
-VMMR3DECL(void) CSAMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
+VMMR3_INT_DECL(void) CSAMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
{
- if (offDelta)
+ if (offDelta && !HMIsEnabled(pVM))
{
/* Adjust pgdir and page bitmap pointers. */
pVM->csam.s.pPDBitmapGC = MMHyperR3ToRC(pVM, pVM->csam.s.pPDGCBitmapHC);
@@ -389,8 +409,11 @@ VMMR3DECL(void) CSAMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
* @returns VBox status code.
* @param pVM Pointer to the VM.
*/
-VMMR3DECL(int) CSAMR3Term(PVM pVM)
+VMMR3_INT_DECL(int) CSAMR3Term(PVM pVM)
{
+ if (HMIsEnabled(pVM))
+ return VINF_SUCCESS;
+
int rc;
rc = CSAMR3Reset(pVM);
@@ -414,10 +437,13 @@ VMMR3DECL(int) CSAMR3Term(PVM pVM)
* @returns VBox status code.
* @param pVM The VM which is reset.
*/
-VMMR3DECL(int) CSAMR3Reset(PVM pVM)
+VMMR3_INT_DECL(int) CSAMR3Reset(PVM pVM)
{
+ if (HMIsEnabled(pVM))
+ return VINF_SUCCESS;
+
/* Clear page bitmaps. */
- for(int i=0;i<CSAM_PGDIRBMP_CHUNKS;i++)
+ for (int i = 0; i < CSAM_PGDIRBMP_CHUNKS; i++)
{
if (pVM->csam.s.pPDBitmapHC[i])
{
@@ -427,15 +453,12 @@ VMMR3DECL(int) CSAMR3Reset(PVM pVM)
}
/* Remove all CSAM page records. */
- while(true)
+ for (;;)
{
PCSAMPAGEREC pPageRec = (PCSAMPAGEREC)RTAvlPVGetBestFit(&pVM->csam.s.pPageTree, 0, true);
- if (pPageRec)
- {
- csamRemovePageRecord(pVM, pPageRec->page.pPageGC);
- }
- else
+ if (!pPageRec)
break;
+ csamRemovePageRecord(pVM, pPageRec->page.pPageGC);
}
Assert(!pVM->csam.s.pPageTree);
@@ -540,6 +563,7 @@ static DECLCALLBACK(int) csamr3Save(PVM pVM, PSSMHANDLE pSSM)
return VINF_SUCCESS;
}
+
/**
* Execute state load operation.
*
@@ -566,12 +590,8 @@ static DECLCALLBACK(int) csamr3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion,
/*
* Restore CSAM structure
*/
-#if 0
- rc = SSMR3GetMem(pSSM, &csamInfo, sizeof(csamInfo));
-#else
RT_ZERO(csamInfo);
- rc = SSMR3GetStructEx(pSSM, &csamInfo, sizeof(csamInfo), SSMSTRUCT_FLAGS_MEM_BAND_AID, &g_aCsamFields[0], NULL);
-#endif
+ rc = SSMR3GetStructEx(pSSM, &csamInfo, sizeof(csamInfo), SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED, &g_aCsamFields[0], NULL);
AssertRCReturn(rc, rc);
pVM->csam.s.fGatesChecked = csamInfo.fGatesChecked;
@@ -587,12 +607,8 @@ static DECLCALLBACK(int) csamr3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion,
memcpy(pVM->csam.s.pvPossibleCodePage, csamInfo.pvPossibleCodePage, sizeof(pVM->csam.s.pvPossibleCodePage));
/* Restore pgdir bitmap (we'll change the pointers next). */
-#if 0
- rc = SSMR3GetMem(pSSM, pVM->csam.s.pPDBitmapHC, CSAM_PGDIRBMP_CHUNKS*sizeof(RTHCPTR));
-#else
rc = SSMR3GetStructEx(pSSM, pVM->csam.s.pPDBitmapHC, sizeof(uint8_t *) * CSAM_PGDIRBMP_CHUNKS,
- SSMSTRUCT_FLAGS_MEM_BAND_AID, &g_aCsamPDBitmapArray[0], NULL);
-#endif
+ SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED, &g_aCsamPDBitmapArray[0], NULL);
AssertRCReturn(rc, rc);
/*
@@ -631,12 +647,8 @@ static DECLCALLBACK(int) csamr3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion,
CSAMPAGEREC page;
PCSAMPAGE pPage;
-#if 0
- rc = SSMR3GetMem(pSSM, &page, sizeof(page));
-#else
RT_ZERO(page);
- rc = SSMR3GetStructEx(pSSM, &page, sizeof(page), SSMSTRUCT_FLAGS_MEM_BAND_AID, &g_aCsamPageRecFields[0], NULL);
-#endif
+ rc = SSMR3GetStructEx(pSSM, &page, sizeof(page), SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED, &g_aCsamPageRecFields[0], NULL);
AssertRCReturn(rc, rc);
/*
@@ -671,17 +683,18 @@ static DECLCALLBACK(int) csamr3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion,
/**
* Convert guest context address to host context pointer
*
- * @returns VBox status code.
+ * @returns Byte pointer (ring-3 context) corresponding to pGCPtr on success,
+ * NULL on failure.
* @param pVM Pointer to the VM.
* @param pCacheRec Address conversion cache record
* @param pGCPtr Guest context pointer
* @returns Host context pointer or NULL in case of an error
*
*/
-static R3PTRTYPE(void *) CSAMGCVirtToHCVirt(PVM pVM, PCSAMP2GLOOKUPREC pCacheRec, RCPTRTYPE(uint8_t *) pGCPtr)
+static uint8_t *csamR3GCVirtToHCVirt(PVM pVM, PCSAMP2GLOOKUPREC pCacheRec, RCPTRTYPE(uint8_t *) pGCPtr)
{
int rc;
- R3PTRTYPE(void *) pHCPtr;
+ void *pHCPtr;
Assert(pVM->cCpus == 1);
PVMCPU pVCpu = VMMGetCpu0(pVM);
@@ -689,7 +702,7 @@ static R3PTRTYPE(void *) CSAMGCVirtToHCVirt(PVM pVM, PCSAMP2GLOOKUPREC pCacheRec
pHCPtr = PATMR3GCPtrToHCPtr(pVM, pGCPtr);
if (pHCPtr)
- return pHCPtr;
+ return (uint8_t *)pHCPtr;
if (pCacheRec->pPageLocStartHC)
{
@@ -716,10 +729,10 @@ static R3PTRTYPE(void *) CSAMGCVirtToHCVirt(PVM pVM, PCSAMP2GLOOKUPREC pCacheRec
return NULL;
}
- pCacheRec->pPageLocStartHC = (R3PTRTYPE(uint8_t*))((RTHCUINTPTR)pHCPtr & PAGE_BASE_HC_MASK);
+ pCacheRec->pPageLocStartHC = (uint8_t*)((uintptr_t)pHCPtr & PAGE_BASE_HC_MASK);
pCacheRec->pGuestLoc = pGCPtr & PAGE_BASE_GC_MASK;
STAM_PROFILE_STOP(&pVM->csam.s.StatTimeAddrConv, a);
- return pHCPtr;
+ return (uint8_t *)pHCPtr;
}
@@ -841,15 +854,17 @@ static int CSAMR3AnalyseCallback(PVM pVM, DISCPUSTATE *pCpu, RCPTRTYPE(uint8_t *
}
break;
+ /* removing breaks win2k guests? */
+ case OP_IRET:
+ if (EMIsRawRing1Enabled(pVM))
+ break;
+ /* no break */
+
case OP_ILLUD2:
/* This appears to be some kind of kernel panic in Linux 2.4; no point to continue. */
case OP_RETN:
case OP_INT3:
case OP_INVALID:
-#if 1
- /* removing breaks win2k guests? */
- case OP_IRET:
-#endif
return VINF_SUCCESS;
}
@@ -895,11 +910,10 @@ static int CSAMR3AnalyseCallback(PVM pVM, DISCPUSTATE *pCpu, RCPTRTYPE(uint8_t *
cbInstrs += cbCurInstr;
{ /* Force pCurInstrHC out of scope after we stop using it (page lock!) */
- uint8_t *pCurInstrHC = 0;
- pCurInstrHC = (uint8_t *)CSAMGCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC);
+ uint8_t *pCurInstrHC = csamR3GCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC);
if (pCurInstrHC == NULL)
{
- Log(("CSAMGCVirtToHCVirt failed for %RRv\n", pCurInstrGC));
+ Log(("csamR3GCVirtToHCVirt failed for %RRv\n", pCurInstrGC));
break;
}
Assert(VALID_PTR(pCurInstrHC));
@@ -914,12 +928,37 @@ static int CSAMR3AnalyseCallback(PVM pVM, DISCPUSTATE *pCpu, RCPTRTYPE(uint8_t *
break;
}
+#ifdef VBOX_WITH_RAW_RING1
+ case OP_MOV:
+ /* mov xx, CS is a dangerous instruction as our raw ring usage leaks through. */
+ if ( EMIsRawRing1Enabled(pVM)
+ && (pCpu->Param2.fUse & DISUSE_REG_SEG)
+ && (pCpu->Param2.Base.idxSegReg == DISSELREG_CS))
+ {
+ Log(("CSAM: Patching dangerous 'mov xx, cs' instruction at %RGv with an int3\n", pCurInstrGC));
+ if (PATMR3HasBeenPatched(pVM, pCurInstrGC) == false)
+ {
+ rc = PATMR3InstallPatch(pVM, pCurInstrGC, (pPage->fCode32) ? PATMFL_CODE32 : 0);
+ if (RT_FAILURE(rc))
+ {
+ Log(("PATMR3InstallPatch failed with %d\n", rc));
+ return VWRN_CONTINUE_ANALYSIS;
+ }
+ }
+ return VWRN_CONTINUE_ANALYSIS;
+ }
+ break;
+#endif
+
case OP_PUSH:
+ /** @todo broken comparison!! should be if ((pCpu->Param1.fUse & DISUSE_REG_SEG) && (pCpu->Param1.Base.idxSegReg == DISSELREG_SS)) */
if (pCpu->pCurInstr->fParam1 != OP_PARM_REG_CS)
break;
/* no break */
+#ifndef VBOX_WITH_SAFE_STR
case OP_STR:
+#endif
case OP_LSL:
case OP_LAR:
case OP_SGDT:
@@ -1077,10 +1116,10 @@ static int csamAnalyseCallCodeStream(PVM pVM, RCPTRTYPE(uint8_t *) pInstrGC, RCP
*/
for (int j = 0; j < 16; j++)
{
- uint8_t *pCurInstrHC = (uint8_t *)CSAMGCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC);
+ uint8_t *pCurInstrHC = csamR3GCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC);
if (pCurInstrHC == NULL)
{
- Log(("CSAMGCVirtToHCVirt failed for %RRv\n", pCurInstrGC));
+ Log(("csamR3GCVirtToHCVirt failed for %RRv\n", pCurInstrGC));
goto done;
}
Assert(VALID_PTR(pCurInstrHC));
@@ -1289,10 +1328,10 @@ static int csamAnalyseCodeStream(PVM pVM, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTY
}
{ /* Force pCurInstrHC out of scope after we stop using it (page lock!) */
- uint8_t *pCurInstrHC = (uint8_t *)CSAMGCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC);
+ uint8_t *pCurInstrHC = csamR3GCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC);
if (pCurInstrHC == NULL)
{
- Log(("CSAMGCVirtToHCVirt failed for %RRv\n", pCurInstrGC));
+ Log(("csamR3GCVirtToHCVirt failed for %RRv\n", pCurInstrGC));
rc = VERR_PATCHING_REFUSED;
goto done;
}
@@ -1589,6 +1628,7 @@ static int csamFlushPage(PVM pVM, RTRCPTR addr, bool fRemovePage)
if (!CSAMIsEnabled(pVM))
return VINF_SUCCESS;
+ Assert(!HMIsEnabled(pVM));
PVMCPU pVCpu = VMMGetCpu0(pVM);
@@ -1689,7 +1729,7 @@ static int csamFlushPage(PVM pVM, RTRCPTR addr, bool fRemovePage)
* @param pVM Pointer to the VM.
* @param addr GC address of the page to flush
*/
-VMMR3DECL(int) CSAMR3FlushPage(PVM pVM, RTRCPTR addr)
+VMMR3_INT_DECL(int) CSAMR3FlushPage(PVM pVM, RTRCPTR addr)
{
return csamFlushPage(pVM, addr, true /* remove page record */);
}
@@ -1701,11 +1741,13 @@ VMMR3DECL(int) CSAMR3FlushPage(PVM pVM, RTRCPTR addr)
* @param pVM Pointer to the VM.
* @param addr GC address of the page to flush
*/
-VMMR3DECL(int) CSAMR3RemovePage(PVM pVM, RTRCPTR addr)
+VMMR3_INT_DECL(int) CSAMR3RemovePage(PVM pVM, RTRCPTR addr)
{
PCSAMPAGEREC pPageRec;
int rc;
+ AssertReturn(!HMIsEnabled(pVM), VERR_CSAM_HM_IPE);
+
addr = addr & PAGE_BASE_GC_MASK;
pPageRec = (PCSAMPAGEREC)RTAvlPVGet(&pVM->csam.s.pPageTree, (AVLPVKEY)(uintptr_t)addr);
@@ -1882,7 +1924,8 @@ VMMR3DECL(int) CSAMR3MonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag)
int rc;
bool fMonitorInvalidation;
Assert(pVM->cCpus == 1);
- PVMCPU pVCpu = VMMGetCpu0(pVM);
+ PVMCPU pVCpu = VMMGetCpu0(pVM);
+ Assert(!HMIsEnabled(pVM));
/* Dirty pages must be handled before calling this function!. */
Assert(!pVM->csam.s.cDirtyPages);
@@ -2002,6 +2045,8 @@ VMMR3DECL(int) CSAMR3MonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag)
*/
VMMR3DECL(int) CSAMR3UnmonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag)
{
+ Assert(!HMIsEnabled(pVM));
+
pPageAddrGC &= PAGE_BASE_GC_MASK;
Log(("CSAMR3UnmonitorPage %RRv %d\n", pPageAddrGC, enmTag));
@@ -2257,12 +2302,13 @@ static void csamMarkCode(PVM pVM, PCSAMPAGE pPage, RTRCPTR pInstr, uint32_t cbIn
* @param cbInstr Instruction size
* @param fScanned Mark as scanned or not
*/
-VMMR3DECL(int) CSAMR3MarkCode(PVM pVM, RTRCPTR pInstr, uint32_t cbInstr, bool fScanned)
+VMMR3_INT_DECL(int) CSAMR3MarkCode(PVM pVM, RTRCPTR pInstr, uint32_t cbInstr, bool fScanned)
{
PCSAMPAGE pPage = 0;
Assert(!fScanned); /* other case not implemented. */
Assert(!PATMIsPatchGCAddr(pVM, pInstr));
+ Assert(!HMIsEnabled(pVM));
if (csamIsCodeScanned(pVM, pInstr, &pPage) == false)
{
@@ -2284,8 +2330,9 @@ VMMR3DECL(int) CSAMR3MarkCode(PVM pVM, RTRCPTR pInstr, uint32_t cbInstr, bool fS
* @param pCtxCore CPU context
* @param pInstrGC Instruction pointer
*/
-VMMR3DECL(int) CSAMR3CheckCodeEx(PVM pVM, PCPUMCTXCORE pCtxCore, RTRCPTR pInstrGC)
+VMMR3_INT_DECL(int) CSAMR3CheckCodeEx(PVM pVM, PCPUMCTXCORE pCtxCore, RTRCPTR pInstrGC)
{
+ Assert(!HMIsEnabled(pVM));
if (EMIsRawRing0Enabled(pVM) == false || PATMIsPatchGCAddr(pVM, pInstrGC) == true)
{
// No use
@@ -2310,10 +2357,11 @@ VMMR3DECL(int) CSAMR3CheckCodeEx(PVM pVM, PCPUMCTXCORE pCtxCore, RTRCPTR pInstrG
* @param pVM Pointer to the VM.
* @param pInstrGC Instruction pointer (0:32 virtual address)
*/
-VMMR3DECL(int) CSAMR3CheckCode(PVM pVM, RTRCPTR pInstrGC)
+VMMR3_INT_DECL(int) CSAMR3CheckCode(PVM pVM, RTRCPTR pInstrGC)
{
int rc;
PCSAMPAGE pPage = NULL;
+ Assert(!HMIsEnabled(pVM));
if ( EMIsRawRing0Enabled(pVM) == false
|| PATMIsPatchGCAddr(pVM, pInstrGC) == true)
@@ -2324,7 +2372,7 @@ VMMR3DECL(int) CSAMR3CheckCode(PVM pVM, RTRCPTR pInstrGC)
if (CSAMIsEnabled(pVM))
{
- /* Cache record for CSAMGCVirtToHCVirt */
+ /* Cache record for csamR3GCVirtToHCVirt */
CSAMP2GLOOKUPREC cacheRec;
RT_ZERO(cacheRec);
@@ -2429,8 +2477,10 @@ static int csamR3FlushCodePages(PVM pVM)
* @param pVM Pointer to the VM.
* @param pVCpu Pointer to the VMCPU.
*/
-VMMR3DECL(int) CSAMR3DoPendingAction(PVM pVM, PVMCPU pVCpu)
+VMMR3_INT_DECL(int) CSAMR3DoPendingAction(PVM pVM, PVMCPU pVCpu)
{
+ AssertReturn(!HMIsEnabled(pVM), VERR_CSAM_HM_IPE);
+
csamR3FlushDirtyPages(pVM);
csamR3FlushCodePages(pVM);
@@ -2446,8 +2496,9 @@ VMMR3DECL(int) CSAMR3DoPendingAction(PVM pVM, PVMCPU pVCpu)
* @param iGate Start gate
* @param cGates Number of gates to check
*/
-VMMR3DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates)
+VMMR3_INT_DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates)
{
+#ifdef VBOX_WITH_RAW_MODE
Assert(pVM->cCpus == 1);
PVMCPU pVCpu = VMMGetCpu0(pVM);
uint16_t cbIDT;
@@ -2458,6 +2509,7 @@ VMMR3DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates)
PVBOXIDTE pGuestIdte;
int rc;
+ AssertReturn(!HMIsEnabled(pVM), VERR_CSAM_HM_IPE);
if (EMIsRawRing0Enabled(pVM) == false)
{
/* Enabling interrupt gates only works when raw ring 0 is enabled. */
@@ -2489,7 +2541,7 @@ VMMR3DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates)
if (pHandler)
{
PCSAMPAGE pPage = NULL;
- CSAMP2GLOOKUPREC cacheRec; /* Cache record for CSAMGCVirtToHCVirt. */
+ CSAMP2GLOOKUPREC cacheRec; /* Cache record for csamR3GCVirtToHCVirt. */
RT_ZERO(cacheRec);
Log(("CSAMCheckGates: checking previous call instruction %RRv\n", pHandler));
@@ -2546,7 +2598,7 @@ VMMR3DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates)
RTRCPTR pHandler;
PCSAMPAGE pPage = NULL;
DBGFSELINFO selInfo;
- CSAMP2GLOOKUPREC cacheRec; /* Cache record for CSAMGCVirtToHCVirt. */
+ CSAMP2GLOOKUPREC cacheRec; /* Cache record for csamR3GCVirtToHCVirt. */
RT_ZERO(cacheRec);
pHandler = VBOXIDTE_OFFSET(*pGuestIdte);
@@ -2636,7 +2688,8 @@ VMMR3DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates)
Log(("Installing %s gate handler for 0x%X at %RRv\n", (pGuestIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_TRAP_32) ? "trap" : "intr", iGate, pHandler));
rc = PATMR3InstallPatch(pVM, pHandler, fPatchFlags);
- if (RT_SUCCESS(rc) || rc == VERR_PATM_ALREADY_PATCHED)
+ if ( RT_SUCCESS(rc)
+ || rc == VERR_PATM_ALREADY_PATCHED)
{
Log(("Gate handler 0x%X is SAFE!\n", iGate));
@@ -2651,6 +2704,7 @@ VMMR3DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates)
}
} /* for */
STAM_PROFILE_STOP(&pVM->csam.s.StatCheckGates, a);
+#endif /* VBOX_WITH_RAW_MODE */
return VINF_SUCCESS;
}
@@ -2663,6 +2717,7 @@ VMMR3DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates)
*/
VMMR3DECL(int) CSAMR3RecordCallAddress(PVM pVM, RTRCPTR GCPtrCall)
{
+ Assert(!HMIsEnabled(pVM));
for (unsigned i=0;i<RT_ELEMENTS(pVM->csam.s.pvCallInstruction);i++)
{
if (pVM->csam.s.pvCallInstruction[i] == GCPtrCall)
@@ -2682,55 +2737,79 @@ VMMR3DECL(int) CSAMR3RecordCallAddress(PVM pVM, RTRCPTR GCPtrCall)
/**
* Query CSAM state (enabled/disabled)
*
- * @returns 0 - disabled, 1 - enabled
- * @param pVM Pointer to the VM.
+ * @returns true if enabled, false otherwise.
+ * @param pUVM The user mode VM handle.
*/
-VMMR3DECL(int) CSAMR3IsEnabled(PVM pVM)
+VMMR3DECL(bool) CSAMR3IsEnabled(PUVM pUVM)
{
- return pVM->fCSAMEnabled;
+ UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
+ PVM pVM = pUVM->pVM;
+ VM_ASSERT_VALID_EXT_RETURN(pVM, false);
+ return CSAMIsEnabled(pVM);
}
-#ifdef VBOX_WITH_DEBUGGER
/**
- * The '.csamoff' command.
+ * Enables or disables code scanning.
*
- * @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.
+ * @returns VBox status code.
+ * @param pUVM The user mode VM handle.
+ * @param fEnabled Whether to enable or disable scanning.
*/
-static DECLCALLBACK(int) csamr3CmdOff(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs)
+VMMR3DECL(int) CSAMR3SetScanningEnabled(PUVM pUVM, bool fEnabled)
{
- DBGC_CMDHLP_REQ_VM_RET(pCmdHlp, pCmd, pVM);
+ UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
+ PVM pVM = pUVM->pVM;
+ VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
+
+ if (HMIsEnabled(pVM))
+ {
+ Assert(!pVM->fCSAMEnabled);
+ return VINF_SUCCESS;
+ }
+
+ int rc;
+ if (fEnabled)
+ rc = CSAMEnableScanning(pVM);
+ else
+ rc = CSAMDisableScanning(pVM);
+ return rc;
+}
+
+
+#ifdef VBOX_WITH_DEBUGGER
+
+/**
+ * @callback_method_impl{FNDBGCCMD, The '.csamoff' command.}
+ */
+static DECLCALLBACK(int) csamr3CmdOff(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
+{
+ DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
NOREF(cArgs); NOREF(paArgs);
- int rc = CSAMDisableScanning(pVM);
+ if (HMR3IsEnabled(pUVM))
+ return DBGCCmdHlpPrintf(pCmdHlp, "CSAM is permanently disabled by HM.\n");
+
+ int rc = CSAMR3SetScanningEnabled(pUVM, false);
if (RT_FAILURE(rc))
- return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "CSAMDisableScanning");
+ return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "CSAMR3SetScanningEnabled");
return DBGCCmdHlpPrintf(pCmdHlp, "CSAM Scanning disabled\n");
}
/**
- * The '.csamon' 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 '.csamon' command.}
*/
-static DECLCALLBACK(int) csamr3CmdOn(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs)
+static DECLCALLBACK(int) csamr3CmdOn(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
{
- DBGC_CMDHLP_REQ_VM_RET(pCmdHlp, pCmd, pVM);
+ DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
NOREF(cArgs); NOREF(paArgs);
- int rc = CSAMEnableScanning(pVM);
+ if (HMR3IsEnabled(pUVM))
+ return DBGCCmdHlpPrintf(pCmdHlp, "CSAM is permanently disabled by HM.\n");
+
+ int rc = CSAMR3SetScanningEnabled(pUVM, true);
if (RT_FAILURE(rc))
- return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "CSAMEnableScanning");
+ return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "CSAMR3SetScanningEnabled");
return DBGCCmdHlpPrintf(pCmdHlp, "CSAM Scanning enabled\n");
}