Lines Matching defs:pVM

72 static DECLCALLBACK(int) csamr3Save(PVM pVM, PSSMHANDLE pSSM);
73 static DECLCALLBACK(int) csamr3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
74 static DECLCALLBACK(int) CSAMCodePageWriteHandler(PVM pVM, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
75 static DECLCALLBACK(int) CSAMCodePageInvalidate(PVM pVM, RTGCPTR GCPtr);
77 bool csamIsCodeScanned(PVM pVM, RTRCPTR pInstr, PCSAMPAGE *pPage);
78 int csamR3CheckPageRecord(PVM pVM, RTRCPTR pInstr);
79 static PCSAMPAGE csamCreatePageRecord(PVM pVM, RTRCPTR GCPtr, CSAMTAG enmTag, bool fCode32, bool fMonitorInvalidation = false);
80 static int csamRemovePageRecord(PVM pVM, RTRCPTR GCPtr);
81 static int csamReinit(PVM pVM);
82 static void csamMarkCode(PVM pVM, PCSAMPAGE pPage, RTRCPTR pInstr, uint32_t opsize, bool fScanned);
83 static int csamAnalyseCodeStream(PVM pVM, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, bool fCode32,
221 * @param pVM Pointer to the VM.
223 VMMR3_INT_DECL(int) CSAMR3Init(PVM pVM)
230 if (HMIsEnabled(pVM))
232 pVM->fCSAMEnabled = false;
233 return SSMR3RegisterStub(pVM, "CSAM", 0);
242 rc = MMR3HyperAllocOnceNoRel(pVM, CSAM_PGDIRBMP_CHUNKS*sizeof(RTHCPTR), 0, MM_TAG_CSAM, (void **)&pVM->csam.s.pPDBitmapHC);
244 rc = MMR3HyperAllocOnceNoRel(pVM, CSAM_PGDIRBMP_CHUNKS*sizeof(RTRCPTR), 0, MM_TAG_CSAM, (void **)&pVM->csam.s.pPDGCBitmapHC);
246 pVM->csam.s.pPDBitmapGC = MMHyperR3ToRC(pVM, pVM->csam.s.pPDGCBitmapHC);
247 pVM->csam.s.pPDHCBitmapGC = MMHyperR3ToRC(pVM, pVM->csam.s.pPDBitmapHC);
249 rc = csamReinit(pVM);
255 rc = SSMR3RegisterInternal(pVM, "CSAM", 0, CSAM_SAVED_STATE_VERSION, sizeof(pVM->csam.s) + PAGE_SIZE*16,
261 STAM_REG(pVM, &pVM->csam.s.StatNrTraps, STAMTYPE_COUNTER, "/CSAM/PageTraps", STAMUNIT_OCCURENCES, "The number of CSAM page traps.");
262 STAM_REG(pVM, &pVM->csam.s.StatDangerousWrite, STAMTYPE_COUNTER, "/CSAM/DangerousWrites", STAMUNIT_OCCURENCES, "The number of dangerous writes that cause a context switch.");
264 STAM_REG(pVM, &pVM->csam.s.StatNrPageNPHC, STAMTYPE_COUNTER, "/CSAM/HC/PageNotPresent", STAMUNIT_OCCURENCES, "The number of CSAM pages marked not present.");
265 STAM_REG(pVM, &pVM->csam.s.StatNrPageNPGC, STAMTYPE_COUNTER, "/CSAM/GC/PageNotPresent", STAMUNIT_OCCURENCES, "The number of CSAM pages marked not present.");
266 STAM_REG(pVM, &pVM->csam.s.StatNrPages, STAMTYPE_COUNTER, "/CSAM/PageRec/AddedRW", STAMUNIT_OCCURENCES, "The number of CSAM page records (RW monitoring).");
267 STAM_REG(pVM, &pVM->csam.s.StatNrPagesInv, STAMTYPE_COUNTER, "/CSAM/PageRec/AddedRWI", STAMUNIT_OCCURENCES, "The number of CSAM page records (RW & invalidation monitoring).");
268 STAM_REG(pVM, &pVM->csam.s.StatNrRemovedPages, STAMTYPE_COUNTER, "/CSAM/PageRec/Removed", STAMUNIT_OCCURENCES, "The number of removed CSAM page records.");
269 STAM_REG(pVM, &pVM->csam.s.StatPageRemoveREMFlush,STAMTYPE_COUNTER, "/CSAM/PageRec/Removed/REMFlush", STAMUNIT_OCCURENCES, "The number of removed CSAM page records that caused a REM flush.");
271 STAM_REG(pVM, &pVM->csam.s.StatNrPatchPages, STAMTYPE_COUNTER, "/CSAM/PageRec/Patch", STAMUNIT_OCCURENCES, "The number of CSAM patch page records.");
272 STAM_REG(pVM, &pVM->csam.s.StatNrUserPages, STAMTYPE_COUNTER, "/CSAM/PageRec/Ignore/User", STAMUNIT_OCCURENCES, "The number of CSAM user page records (ignored).");
273 STAM_REG(pVM, &pVM->csam.s.StatPagePATM, STAMTYPE_COUNTER, "/CSAM/PageRec/Type/PATM", STAMUNIT_OCCURENCES, "The number of PATM page records.");
274 STAM_REG(pVM, &pVM->csam.s.StatPageCSAM, STAMTYPE_COUNTER, "/CSAM/PageRec/Type/CSAM", STAMUNIT_OCCURENCES, "The number of CSAM page records.");
275 STAM_REG(pVM, &pVM->csam.s.StatPageREM, STAMTYPE_COUNTER, "/CSAM/PageRec/Type/REM", STAMUNIT_OCCURENCES, "The number of REM page records.");
276 STAM_REG(pVM, &pVM->csam.s.StatPageMonitor, STAMTYPE_COUNTER, "/CSAM/PageRec/Monitored", STAMUNIT_OCCURENCES, "The number of monitored pages.");
278 STAM_REG(pVM, &pVM->csam.s.StatCodePageModified, STAMTYPE_COUNTER, "/CSAM/Monitor/DirtyPage", STAMUNIT_OCCURENCES, "The number of code page modifications.");
280 STAM_REG(pVM, &pVM->csam.s.StatNrFlushes, STAMTYPE_COUNTER, "/CSAM/PageFlushes", STAMUNIT_OCCURENCES, "The number of CSAM page flushes.");
281 STAM_REG(pVM, &pVM->csam.s.StatNrFlushesSkipped, STAMTYPE_COUNTER, "/CSAM/PageFlushesSkipped", STAMUNIT_OCCURENCES, "The number of CSAM page flushes that were skipped.");
282 STAM_REG(pVM, &pVM->csam.s.StatNrKnownPagesHC, STAMTYPE_COUNTER, "/CSAM/HC/KnownPageRecords", STAMUNIT_OCCURENCES, "The number of known CSAM page records.");
283 STAM_REG(pVM, &pVM->csam.s.StatNrKnownPagesGC, STAMTYPE_COUNTER, "/CSAM/GC/KnownPageRecords", STAMUNIT_OCCURENCES, "The number of known CSAM page records.");
284 STAM_REG(pVM, &pVM->csam.s.StatNrInstr, STAMTYPE_COUNTER, "/CSAM/ScannedInstr", STAMUNIT_OCCURENCES, "The number of scanned instructions.");
285 STAM_REG(pVM, &pVM->csam.s.StatNrBytesRead, STAMTYPE_COUNTER, "/CSAM/BytesRead", STAMUNIT_OCCURENCES, "The number of bytes read for scanning.");
286 STAM_REG(pVM, &pVM->csam.s.StatNrOpcodeRead, STAMTYPE_COUNTER, "/CSAM/OpcodeBytesRead", STAMUNIT_OCCURENCES, "The number of opcode bytes read by the recompiler.");
288 STAM_REG(pVM, &pVM->csam.s.StatBitmapAlloc, STAMTYPE_COUNTER, "/CSAM/Alloc/PageBitmap", STAMUNIT_OCCURENCES, "The number of page bitmap allocations.");
290 STAM_REG(pVM, &pVM->csam.s.StatInstrCacheHit, STAMTYPE_COUNTER, "/CSAM/Cache/Hit", STAMUNIT_OCCURENCES, "The number of dangerous instruction cache hits.");
291 STAM_REG(pVM, &pVM->csam.s.StatInstrCacheMiss, STAMTYPE_COUNTER, "/CSAM/Cache/Miss", STAMUNIT_OCCURENCES, "The number of dangerous instruction cache misses.");
293 STAM_REG(pVM, &pVM->csam.s.StatScanNextFunction, STAMTYPE_COUNTER, "/CSAM/Function/Scan/Success", STAMUNIT_OCCURENCES, "The number of found functions beyond the ret border.");
294 STAM_REG(pVM, &pVM->csam.s.StatScanNextFunctionFailed, STAMTYPE_COUNTER, "/CSAM/Function/Scan/Failed", STAMUNIT_OCCURENCES, "The number of refused functions beyond the ret border.");
296 STAM_REG(pVM, &pVM->csam.s.StatTime, STAMTYPE_PROFILE, "/PROF/CSAM/Scan", STAMUNIT_TICKS_PER_CALL, "Scanning overhead.");
297 STAM_REG(pVM, &pVM->csam.s.StatTimeCheckAddr, STAMTYPE_PROFILE, "/PROF/CSAM/CheckAddr", STAMUNIT_TICKS_PER_CALL, "Address check overhead.");
298 STAM_REG(pVM, &pVM->csam.s.StatTimeAddrConv, STAMTYPE_PROFILE, "/PROF/CSAM/AddrConv", STAMUNIT_TICKS_PER_CALL, "Address conversion overhead.");
299 STAM_REG(pVM, &pVM->csam.s.StatTimeFlushPage, STAMTYPE_PROFILE, "/PROF/CSAM/FlushPage", STAMUNIT_TICKS_PER_CALL, "Page flushing overhead.");
300 STAM_REG(pVM, &pVM->csam.s.StatTimeDisasm, STAMTYPE_PROFILE, "/PROF/CSAM/Disasm", STAMUNIT_TICKS_PER_CALL, "Disassembly overhead.");
301 STAM_REG(pVM, &pVM->csam.s.StatFlushDirtyPages, STAMTYPE_PROFILE, "/PROF/CSAM/FlushDirtyPage", STAMUNIT_TICKS_PER_CALL, "Dirty page flushing overhead.");
302 STAM_REG(pVM, &pVM->csam.s.StatCheckGates, STAMTYPE_PROFILE, "/PROF/CSAM/CheckGates", STAMUNIT_TICKS_PER_CALL, "CSAMR3CheckGates overhead.");
308 rc = CFGMR3QueryBool(CFGMR3GetRoot(pVM), "CSAMEnabled", &fEnabled);
316 CSAMEnableScanning(pVM);
337 * @param pVM The VM.
339 static int csamReinit(PVM pVM)
345 AssertRelease(sizeof(pVM->csam.s) <= sizeof(pVM->csam.padding));
346 AssertRelease(!HMIsEnabled(pVM));
351 pVM->csam.s.offVM = RT_OFFSETOF(VM, patm);
353 pVM->csam.s.fGatesChecked = false;
354 pVM->csam.s.fScanningStarted = false;
356 PVMCPU pVCpu = &pVM->aCpus[0]; /* raw mode implies 1 VPCU */
358 pVM->csam.s.cDirtyPages = 0;
360 memset(pVM->csam.s.pvDirtyBasePage, 0, sizeof(pVM->csam.s.pvDirtyBasePage));
361 memset(pVM->csam.s.pvDirtyFaultPage, 0, sizeof(pVM->csam.s.pvDirtyFaultPage));
363 memset(&pVM->csam.s.aDangerousInstr, 0, sizeof(pVM->csam.s.aDangerousInstr));
364 pVM->csam.s.cDangerousInstr = 0;
365 pVM->csam.s.iDangerousInstr = 0;
367 memset(pVM->csam.s.pvCallInstruction, 0, sizeof(pVM->csam.s.pvCallInstruction));
368 pVM->csam.s.iCallInstruction = 0;
381 * @param pVM The VM.
384 VMMR3_INT_DECL(void) CSAMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
386 if (offDelta && !HMIsEnabled(pVM))
389 pVM->csam.s.pPDBitmapGC = MMHyperR3ToRC(pVM, pVM->csam.s.pPDGCBitmapHC);
390 pVM->csam.s.pPDHCBitmapGC = MMHyperR3ToRC(pVM, pVM->csam.s.pPDBitmapHC);
394 if (pVM->csam.s.pPDGCBitmapHC[i])
396 pVM->csam.s.pPDGCBitmapHC[i] += offDelta;
410 * @param pVM Pointer to the VM.
412 VMMR3_INT_DECL(int) CSAMR3Term(PVM pVM)
414 if (HMIsEnabled(pVM))
419 rc = CSAMR3Reset(pVM);
426 if (pVM->csam.s.pPDBitmapHC[i])
427 MMHyperFree(pVM, pVM->csam.s.pPDBitmapHC[i]);
438 * @param pVM The VM which is reset.
440 VMMR3_INT_DECL(int) CSAMR3Reset(PVM pVM)
442 if (HMIsEnabled(pVM))
448 if (pVM->csam.s.pPDBitmapHC[i])
451 ASMMemZero32(pVM->csam.s.pPDBitmapHC[i], CSAM_PAGE_BITMAP_SIZE);
458 PCSAMPAGEREC pPageRec = (PCSAMPAGEREC)RTAvlPVGetBestFit(&pVM->csam.s.pPageTree, 0, true);
461 csamRemovePageRecord(pVM, pPageRec->page.pPageGC);
463 Assert(!pVM->csam.s.pPageTree);
465 csamReinit(pVM);
498 PVM pVM = (PVM)pVM1;
501 PSSMHANDLE pSSM = pVM->csam.s.savedstate.pSSM;
521 * @param pVM Pointer to the VM.
524 static DECLCALLBACK(int) csamr3Save(PVM pVM, PSSMHANDLE pSSM)
526 CSAM csamInfo = pVM->csam.s;
533 RTAvlPVDoWithAll(&pVM->csam.s.pPageTree, true, CountRecord, &csamInfo.savedstate.cPageRecords);
538 pVM->csam.s.savedstate.pSSM = pSSM;
559 rc = RTAvlPVDoWithAll(&pVM->csam.s.pPageTree, true, SavePageState, pVM);
571 * @param pVM Pointer to the VM.
576 static DECLCALLBACK(int) csamr3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
588 pVM->csam.s.savedstate.pSSM = pSSM;
597 pVM->csam.s.fGatesChecked = csamInfo.fGatesChecked;
598 pVM->csam.s.fScanningStarted = csamInfo.fScanningStarted;
601 pVM->csam.s.cDirtyPages = csamInfo.cDirtyPages;
602 memcpy(pVM->csam.s.pvDirtyBasePage, csamInfo.pvDirtyBasePage, sizeof(pVM->csam.s.pvDirtyBasePage));
603 memcpy(pVM->csam.s.pvDirtyFaultPage, csamInfo.pvDirtyFaultPage, sizeof(pVM->csam.s.pvDirtyFaultPage));
606 pVM->csam.s.cPossibleCodePages = csamInfo.cPossibleCodePages;
607 memcpy(pVM->csam.s.pvPossibleCodePage, csamInfo.pvPossibleCodePage, sizeof(pVM->csam.s.pvPossibleCodePage));
610 rc = SSMR3GetStructEx(pSSM, pVM->csam.s.pPDBitmapHC, sizeof(uint8_t *) * CSAM_PGDIRBMP_CHUNKS,
619 if(pVM->csam.s.pPDBitmapHC[i])
621 rc = MMHyperAlloc(pVM, CSAM_PAGE_BITMAP_SIZE, 0, MM_TAG_CSAM, (void **)&pVM->csam.s.pPDBitmapHC[i]);
628 pVM->csam.s.pPDGCBitmapHC[i] = MMHyperR3ToRC(pVM, pVM->csam.s.pPDBitmapHC[i]);
629 Assert(pVM->csam.s.pPDGCBitmapHC[i]);
632 rc = SSMR3GetMem(pSSM, pVM->csam.s.pPDBitmapHC[i], CSAM_PAGE_BITMAP_SIZE);
637 Assert(!pVM->csam.s.pPDGCBitmapHC[i]);
638 pVM->csam.s.pPDGCBitmapHC[i] = 0;
657 pPage = csamCreatePageRecord(pVM, page.page.pPageGC, page.page.enmTag, page.page.fCode32, page.page.fMonitorInvalidation);
677 memset(&pVM->csam.s.aDangerousInstr, 0, sizeof(pVM->csam.s.aDangerousInstr));
678 pVM->csam.s.cDangerousInstr = 0;
679 pVM->csam.s.iDangerousInstr = 0;
688 * @param pVM Pointer to the VM.
694 static uint8_t *csamR3GCVirtToHCVirt(PVM pVM, PCSAMP2GLOOKUPREC pCacheRec, RCPTRTYPE(uint8_t *) pGCPtr)
698 Assert(pVM->cCpus == 1);
699 PVMCPU pVCpu = VMMGetCpu0(pVM);
701 STAM_PROFILE_START(&pVM->csam.s.StatTimeAddrConv, a);
703 pHCPtr = PATMR3GCPtrToHCPtr(pVM, pGCPtr);
712 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeAddrConv, a);
720 PGMPhysReleasePageMappingLock(pVM, &pCacheRec->Lock);
728 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeAddrConv, a);
734 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeAddrConv, a);
742 PVM pVM;
765 int rc = PATMR3ReadOrgInstr(pDisInfo->pVM, pDis->uInstrAddr + offInstr, &pDis->abInstr[offInstr], cbRead, &cbRead);
791 || PATMIsPatchGCAddr(pDisInfo->pVM, uSrcAddr) /** @todo does CSAM actually analyze patch code, or is this just a copy&past check? */
801 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pDisInfo->pVM), &pDis->abInstr[offInstr], uSrcAddr, cbMinRead);
809 DECLINLINE(int) csamR3DISInstr(PVM pVM, RTRCPTR InstrGC, uint8_t *InstrHC, DISCPUMODE enmCpuMode,
812 CSAMDISINFO DisInfo = { pVM, InstrHC };
831 * @param pVM Pointer to the VM.
839 static int CSAMR3AnalyseCallback(PVM pVM, DISCPUSTATE *pCpu, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC,
859 if (EMIsRawRing1Enabled(pVM))
892 PATMR3AddHint(pVM, pCurInstrGC, (fCode32) ? PATMFL_CODE32 : 0);
902 if (csamIsCodeScanned(pVM, pCurInstrGC + cbCurInstr, &pPage) == true)
906 PATMR3DetectConflict(pVM, pCurInstrGC, pCurInstrGC + cbCurInstr);
913 uint8_t *pCurInstrHC = csamR3GCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC);
921 rc = csamR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? DISCPUMODE_32BIT : DISCPUMODE_16BIT,
934 if ( EMIsRawRing1Enabled(pVM)
939 if (PATMR3HasBeenPatched(pVM, pCurInstrGC) == false)
941 rc = PATMR3InstallPatch(pVM, pCurInstrGC, (pPage->fCode32) ? PATMFL_CODE32 : 0);
1014 if (PATMR3HasBeenPatched(pVM, pCurInstrGC) == false)
1016 rc = PATMR3InstallPatch(pVM, pCurInstrGC, (pPage->fCode32) ? PATMFL_CODE32 : 0);
1060 * @param pVM Pointer to the VM.
1068 static int csamAnalyseCallCodeStream(PVM pVM, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, bool fCode32,
1082 rc = csamAnalyseCodeStream(pVM, pInstrGC, pCurInstrGC, fCode32, pfnCSAMR3Analyse, pUserData, pCacheRec);
1091 if (csamIsCodeScanned(pVM, pCurInstrGC, &pPage) == false)
1102 pPage = csamCreatePageRecord(pVM, pCurInstrGC, CSAM_TAG_CSAM, fCode32);
1119 uint8_t *pCurInstrHC = csamR3GCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC);
1127 STAM_PROFILE_START(&pVM->csam.s.StatTimeDisasm, a);
1129 rc2 = csamR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? DISCPUMODE_32BIT : DISCPUMODE_16BIT,
1133 rc2 = csamR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, (fCode32) ? DISCPUMODE_32BIT : DISCPUMODE_16BIT,
1136 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeDisasm, a);
1143 STAM_COUNTER_ADD(&pVM->csam.s.StatNrBytesRead, cbInstr);
1150 if (!PGMGstIsPagePresent(pVM, pCurInstrGC + cbInstr - 1))
1157 csamR3CheckPageRecord(pVM, pCurInstrGC + cbInstr - 1);
1183 STAM_COUNTER_INC(&pVM->csam.s.StatScanNextFunctionFailed);
1195 STAM_COUNTER_INC(&pVM->csam.s.StatScanNextFunctionFailed);
1199 if (csamIsCodeScanned(pVM, pCurInstrGC, &pPage) == false)
1208 STAM_COUNTER_INC(&pVM->csam.s.StatScanNextFunction);
1209 csamAnalyseCallCodeStream(pVM, pInstrGC, pCurInstrGC, fCode32, pfnCSAMR3Analyse, pUserData, pCacheRec);
1221 STAM_COUNTER_INC(&pVM->csam.s.StatScanNextFunctionFailed);
1225 if (csamIsCodeScanned(pVM, pCurInstrGC, &pPage) == false)
1234 STAM_COUNTER_INC(&pVM->csam.s.StatScanNextFunction);
1235 csamAnalyseCallCodeStream(pVM, pInstrGC, pCurInstrGC, fCode32, pfnCSAMR3Analyse, pUserData, pCacheRec);
1241 STAM_COUNTER_INC(&pVM->csam.s.StatScanNextFunctionFailed);
1245 csamMarkCode(pVM, pPage, pCurInstrGC, cbInstr, true);
1264 * @param pVM Pointer to the VM.
1272 static int csamAnalyseCodeStream(PVM pVM, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, bool fCode32,
1280 Assert(pVM->cCpus == 1);
1281 PVMCPU pVCpu = VMMGetCpu0(pVM);
1289 pVM->csam.s.fScanningStarted = true;
1305 Assert(!PATMIsPatchGCAddr(pVM, pCurInstrGC));
1306 csamR3CheckPageRecord(pVM, pCurInstrGC);
1310 if (csamIsCodeScanned(pVM, pCurInstrGC, &pPage) == false)
1315 pPage = csamCreatePageRecord(pVM, pCurInstrGC, CSAM_TAG_CSAM, fCode32);
1331 uint8_t *pCurInstrHC = csamR3GCVirtToHCVirt(pVM, pCacheRec, pCurInstrGC);
1340 STAM_PROFILE_START(&pVM->csam.s.StatTimeDisasm, a);
1342 rc2 = csamR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, fCode32 ? DISCPUMODE_32BIT : DISCPUMODE_16BIT,
1346 rc2 = csamR3DISInstr(pVM, pCurInstrGC, pCurInstrHC, fCode32 ? DISCPUMODE_32BIT : DISCPUMODE_16BIT,
1349 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeDisasm, a);
1358 STAM_COUNTER_ADD(&pVM->csam.s.StatNrBytesRead, cbInstr);
1360 csamMarkCode(pVM, pPage, pCurInstrGC, cbInstr, true);
1375 csamR3CheckPageRecord(pVM, pCurInstrGC + cbInstr - 1);
1382 AssertMsg(pfnCSAMR3Analyse(pVM, &cpu, pInstrGC, pCurInstrGC, pCacheRec, (void *)pPage) == VWRN_CONTINUE_ANALYSIS, ("Instruction incorrectly marked harmless?!?!?\n"));
1398 rc = pfnCSAMR3Analyse(pVM, &cpu, pInstrGC, pCurInstrGC, pCacheRec, (void *)pPage);
1422 Assert(!PATMIsPatchGCAddr(pVM, addr));
1425 PATMR3DetectConflict(pVM, pCurInstrGC, addr);
1438 csamR3CheckPageRecord(pVM, addr);
1442 if (csamIsCodeScanned(pVM, addr, &pJmpPage) == false)
1447 pJmpPage = csamCreatePageRecord(pVM, addr, CSAM_TAG_CSAM, fCode32);
1456 rc = csamAnalyseCallCodeStream(pVM, pInstrGC, addr, fCode32, pfnCSAMR3Analyse, (void *)pJmpPage, pCacheRec);
1458 rc = csamAnalyseCodeStream(pVM, pInstrGC, addr, fCode32, pfnCSAMR3Analyse, (void *)pJmpPage, pCacheRec);
1508 if (csamIsCodeScanned(pVM, addr, &pJmpPage) == false)
1513 pJmpPage = csamCreatePageRecord(pVM, addr, CSAM_TAG_CSAM, fCode32);
1521 rc = csamAnalyseCodeStream(pVM, pInstrGC, addr, fCode32, pfnCSAMR3Analyse, (void *)pJmpPage, pCacheRec);
1551 * @param pVM Pointer to the VM.
1554 uint64_t csamR3CalcPageHash(PVM pVM, RTRCPTR pInstr)
1559 Assert(pVM->cCpus == 1);
1560 PVMCPU pVCpu = VMMGetCpu0(pVM);
1617 * @param pVM Pointer to the VM.
1621 static int csamFlushPage(PVM pVM, RTRCPTR addr, bool fRemovePage)
1627 Assert(pVM->cCpus == 1 || !CSAMIsEnabled(pVM));
1629 if (!CSAMIsEnabled(pVM))
1631 Assert(!HMIsEnabled(pVM));
1633 PVMCPU pVCpu = VMMGetCpu0(pVM);
1635 STAM_PROFILE_START(&pVM->csam.s.StatTimeFlushPage, a);
1642 if (pVM->csam.s.pPageTree == NULL)
1644 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeFlushPage, a);
1652 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeFlushPage, a);
1663 STAM_COUNTER_ADD(&pVM->csam.s.StatNrFlushesSkipped, 1);
1664 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeFlushPage, a);
1672 pPageRec = (PCSAMPAGEREC)RTAvlPVGet(&pVM->csam.s.pPageTree, (AVLPVKEY)(uintptr_t)addr);
1678 STAM_COUNTER_ADD(&pVM->csam.s.StatNrFlushesSkipped, 1);
1679 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeFlushPage, a);
1685 STAM_COUNTER_ADD(&pVM->csam.s.StatNrFlushes, 1);
1688 csamRemovePageRecord(pVM, addr);
1691 CSAMMarkPage(pVM, addr, false);
1696 pPageRec->page.u64Hash = csamR3CalcPageHash(pVM, addr);
1700 pPageRec->page.pBitmap = (uint8_t *)MMR3HeapAllocZ(pVM, MM_TAG_CSAM_PATCH, CSAM_PAGE_BITMAP_SIZE);
1713 PATMR3FlushPage(pVM, addr);
1715 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeFlushPage, a);
1720 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeFlushPage, a);
1729 * @param pVM Pointer to the VM.
1732 VMMR3_INT_DECL(int) CSAMR3FlushPage(PVM pVM, RTRCPTR addr)
1734 return csamFlushPage(pVM, addr, true /* remove page record */);
1741 * @param pVM Pointer to the VM.
1744 VMMR3_INT_DECL(int) CSAMR3RemovePage(PVM pVM, RTRCPTR addr)
1749 AssertReturn(!HMIsEnabled(pVM), VERR_CSAM_HM_IPE);
1753 pPageRec = (PCSAMPAGEREC)RTAvlPVGet(&pVM->csam.s.pPageTree, (AVLPVKEY)(uintptr_t)addr);
1756 rc = csamRemovePageRecord(pVM, addr);
1758 PATMR3FlushPage(pVM, addr);
1768 * @param pVM Pointer to the VM.
1771 int csamR3CheckPageRecord(PVM pVM, RTRCPTR pInstrGC)
1778 pPageRec = (PCSAMPAGEREC)RTAvlPVGet(&pVM->csam.s.pPageTree, (AVLPVKEY)(uintptr_t)pInstrGC);
1781 u64hash = csamR3CalcPageHash(pVM, pInstrGC);
1783 csamFlushPage(pVM, pInstrGC, false /* don't remove page record */);
1812 * @param pVM Pointer to the VM.
1818 static PCSAMPAGE csamCreatePageRecord(PVM pVM, RTRCPTR GCPtr, CSAMTAG enmTag, bool fCode32, bool fMonitorInvalidation)
1823 Assert(pVM->cCpus == 1);
1824 PVMCPU pVCpu = VMMGetCpu0(pVM);
1828 pPage = (PCSAMPAGEREC)MMR3HeapAllocZ(pVM, MM_TAG_CSAM_PATCH, sizeof(CSAMPAGEREC));
1842 pPage->page.pBitmap = (uint8_t *)MMR3HeapAllocZ(pVM, MM_TAG_CSAM_PATCH, PAGE_SIZE/sizeof(uint8_t));
1846 pPage->page.u64Hash = csamR3CalcPageHash(pVM, GCPtr);
1847 ret = RTAvlPVInsert(&pVM->csam.s.pPageTree, &pPage->Core);
1861 rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_WRITE, GCPtr, GCPtr + (PAGE_SIZE - 1) /* inclusive! */,
1878 STAM_COUNTER_INC(&pVM->csam.s.StatPageMonitor);
1891 STAM_COUNTER_INC(&pVM->csam.s.StatPageCSAM);
1894 STAM_COUNTER_INC(&pVM->csam.s.StatPagePATM);
1897 STAM_COUNTER_INC(&pVM->csam.s.StatPageREM);
1906 STAM_COUNTER_INC(&pVM->csam.s.StatNrPages);
1908 STAM_COUNTER_INC(&pVM->csam.s.StatNrPagesInv);
1917 * @param pVM Pointer to the VM.
1921 VMMR3DECL(int) CSAMR3MonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag)
1926 Assert(pVM->cCpus == 1);
1927 PVMCPU pVCpu = VMMGetCpu0(pVM);
1928 Assert(!HMIsEnabled(pVM));
1931 Assert(!pVM->csam.s.cDirtyPages);
1933 if (pVM->csam.s.fScanningStarted == false)
1943 pPageRec = (PCSAMPAGEREC)RTAvlPVGet(&pVM->csam.s.pPageTree, (AVLPVKEY)(uintptr_t)pPageAddrGC);
1954 STAM_COUNTER_INC(&pVM->csam.s.StatNrUserPages);
1958 csamCreatePageRecord(pVM, pPageAddrGC, enmTag, true /* 32 bits code */, fMonitorInvalidation);
1960 pPageRec = (PCSAMPAGEREC)RTAvlPVGet(&pVM->csam.s.pPageTree, (AVLPVKEY)(uintptr_t)pPageAddrGC);
1974 rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_WRITE, pPageAddrGC, pPageAddrGC + (PAGE_SIZE - 1) /* inclusive! */,
1990 STAM_COUNTER_INC(&pVM->csam.s.StatPageMonitor);
2000 PGMHandlerVirtualChangeInvalidateCallback(pVM, pPageRec->page.pPageGC, CSAMCodePageInvalidate);
2002 STAM_COUNTER_INC(&pVM->csam.s.StatNrPagesInv);
2042 * @param pVM Pointer to the VM.
2046 VMMR3DECL(int) CSAMR3UnmonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag)
2048 Assert(!HMIsEnabled(pVM));
2059 pPageRec = (PCSAMPAGEREC)RTAvlPVGet(&pVM->csam.s.pPageTree, (AVLPVKEY)(uintptr_t)pPageAddrGC);
2062 return CSAMR3RemovePage(pVM, pPageAddrGC);
2069 * @param pVM Pointer to the VM.
2072 static int csamRemovePageRecord(PVM pVM, RTRCPTR GCPtr)
2075 Assert(pVM->cCpus == 1);
2076 PVMCPU pVCpu = VMMGetCpu0(pVM);
2079 pPageRec = (PCSAMPAGEREC)RTAvlPVRemove(&pVM->csam.s.pPageTree, (AVLPVKEY)(uintptr_t)GCPtr);
2083 STAM_COUNTER_INC(&pVM->csam.s.StatNrRemovedPages);
2092 STAM_COUNTER_DEC(&pVM->csam.s.StatPageMonitor);
2093 PGMHandlerVirtualDeregister(pVM, GCPtr);
2098 STAM_COUNTER_INC(&pVM->csam.s.StatPageRemoveREMFlush);
2107 STAM_COUNTER_DEC(&pVM->csam.s.StatPageCSAM);
2110 STAM_COUNTER_DEC(&pVM->csam.s.StatPagePATM);
2113 STAM_COUNTER_DEC(&pVM->csam.s.StatPageREM);
2132 * @param pVM Pointer to the VM.
2136 static DECLCALLBACK(void) CSAMDelayedWriteHandler(PVM pVM, RTRCPTR GCPtr, size_t cbBuf)
2138 int rc = PATMR3PatchWrite(pVM, GCPtr, (uint32_t)cbBuf);
2150 * @param pVM Pointer to the VM.
2158 static DECLCALLBACK(int) CSAMCodePageWriteHandler(PVM pVM, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser)
2173 if (VM_IS_EMT(pVM))
2174 rc = PATMR3PatchWrite(pVM, GCPtr, (uint32_t)cbBuf);
2183 rc = VMR3ReqCallVoidNoWait(pVM, VMCPUID_ANY, (PFNRT)CSAMDelayedWriteHandler, 3, pVM, (RTRCPTR)GCPtr, cbBuf);
2193 * @param pVM Pointer to the VM.
2196 static DECLCALLBACK(int) CSAMCodePageInvalidate(PVM pVM, RTGCPTR GCPtr)
2201 csamFlushPage(pVM, GCPtr, false /* don't remove page! */);
2210 * @param pVM Pointer to the VM.
2214 bool csamIsCodeScanned(PVM pVM, RTRCPTR pInstr, PCSAMPAGE *pPage)
2219 STAM_PROFILE_START(&pVM->csam.s.StatTimeCheckAddr, a);
2230 STAM_COUNTER_ADD(&pVM->csam.s.StatNrKnownPagesHC, 1);
2231 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeCheckAddr, a);
2234 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeCheckAddr, a);
2238 pPageRec = (PCSAMPAGEREC)RTAvlPVGet(&pVM->csam.s.pPageTree, (AVLPVKEY)(uintptr_t)pInstr);
2244 STAM_COUNTER_ADD(&pVM->csam.s.StatNrKnownPagesHC, 1);
2245 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeCheckAddr, a);
2253 STAM_PROFILE_STOP(&pVM->csam.s.StatTimeCheckAddr, a);
2260 * @param pVM Pointer to the VM.
2266 static void csamMarkCode(PVM pVM, PCSAMPAGE pPage, RTRCPTR pInstr, uint32_t cbInstr, bool fScanned)
2269 CSAMMarkPage(pVM, pInstr, fScanned);
2281 STAM_COUNTER_ADD(&pVM->csam.s.StatNrInstr, 1);
2300 * @param pVM Pointer to the VM.
2305 VMMR3_INT_DECL(int) CSAMR3MarkCode(PVM pVM, RTRCPTR pInstr, uint32_t cbInstr, bool fScanned)
2310 Assert(!PATMIsPatchGCAddr(pVM, pInstr));
2311 Assert(!HMIsEnabled(pVM));
2313 if (csamIsCodeScanned(pVM, pInstr, &pPage) == false)
2320 csamMarkCode(pVM, pPage, pInstr, cbInstr, fScanned);
2329 * @param pVM Pointer to the VM.
2333 VMMR3_INT_DECL(int) CSAMR3CheckCodeEx(PVM pVM, PCPUMCTX pCtx, RTRCPTR pInstrGC)
2335 Assert(!HMIsEnabled(pVM));
2336 if (EMIsRawRing0Enabled(pVM) == false || PATMIsPatchGCAddr(pVM, pInstrGC) == true)
2342 if (CSAMIsEnabled(pVM))
2345 Assert(CPUMGetGuestCodeBits(VMMGetCpu0(pVM)) == 32);
2347 pInstrGC = SELMToFlat(pVM, DISSELREG_CS, CPUMCTX2CORE(pCtx), pInstrGC);
2348 return CSAMR3CheckCode(pVM, pInstrGC);
2357 * @param pVM Pointer to the VM.
2360 VMMR3_INT_DECL(int) CSAMR3CheckCode(PVM pVM, RTRCPTR pInstrGC)
2364 Assert(!HMIsEnabled(pVM));
2366 if ( EMIsRawRing0Enabled(pVM) == false
2367 || PATMIsPatchGCAddr(pVM, pInstrGC) == true)
2373 if (CSAMIsEnabled(pVM))
2379 STAM_PROFILE_START(&pVM->csam.s.StatTime, a);
2380 rc = csamAnalyseCallCodeStream(pVM, pInstrGC, pInstrGC, true /* 32 bits code */, CSAMR3AnalyseCallback, pPage, &cacheRec);
2381 STAM_PROFILE_STOP(&pVM->csam.s.StatTime, a);
2383 PGMPhysReleasePageMappingLock(pVM, &cacheRec.Lock);
2398 * @param pVM Pointer to the VM.
2400 static int csamR3FlushDirtyPages(PVM pVM)
2402 Assert(pVM->cCpus == 1);
2403 PVMCPU pVCpu = VMMGetCpu0(pVM);
2405 STAM_PROFILE_START(&pVM->csam.s.StatFlushDirtyPages, a);
2407 for (uint32_t i=0;i<pVM->csam.s.cDirtyPages;i++)
2411 RTRCPTR GCPtr = pVM->csam.s.pvDirtyBasePage[i];
2417 REMR3NotifyCodePageChanged(pVM, pVCpu, GCPtr);
2421 rc = PGMShwMakePageReadonly(pVCpu, pVM->csam.s.pvDirtyFaultPage[i], 0 /*fFlags*/);
2424 Log(("CSAMR3FlushDirtyPages: flush %RRv (modifypage rc=%Rrc)\n", pVM->csam.s.pvDirtyBasePage[i], rc));
2426 pPageRec = (PCSAMPAGEREC)RTAvlPVGet(&pVM->csam.s.pPageTree, (AVLPVKEY)(uintptr_t)GCPtr);
2437 csamRemovePageRecord(pVM, GCPtr);
2438 STAM_COUNTER_INC(&pVM->csam.s.StatNrUserPages);
2442 pVM->csam.s.cDirtyPages = 0;
2443 STAM_PROFILE_STOP(&pVM->csam.s.StatFlushDirtyPages, a);
2451 * @param pVM Pointer to the VM.
2453 static int csamR3FlushCodePages(PVM pVM)
2455 Assert(pVM->cCpus == 1);
2456 PVMCPU pVCpu = VMMGetCpu0(pVM);
2458 for (uint32_t i=0;i<pVM->csam.s.cPossibleCodePages;i++)
2460 RTRCPTR GCPtr = pVM->csam.s.pvPossibleCodePage[i];
2467 CSAMMarkPage(pVM, GCPtr, false);
2469 pVM->csam.s.cPossibleCodePages = 0;
2477 * @param pVM Pointer to the VM.
2480 VMMR3_INT_DECL(int) CSAMR3DoPendingAction(PVM pVM, PVMCPU pVCpu)
2482 AssertReturn(!HMIsEnabled(pVM), VERR_CSAM_HM_IPE);
2484 csamR3FlushDirtyPages(pVM);
2485 csamR3FlushCodePages(pVM);
2495 * @param pVM Pointer to the VM.
2499 VMMR3_INT_DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates)
2502 Assert(pVM->cCpus == 1);
2503 PVMCPU pVCpu = VMMGetCpu0(pVM);
2512 AssertReturn(!HMIsEnabled(pVM), VERR_CSAM_HM_IPE);
2513 if (EMIsRawRing0Enabled(pVM) == false)
2521 if ( !pVM->csam.s.fGatesChecked
2526 if ( pVM->csam.s.fGatesChecked
2536 pVM->csam.s.fGatesChecked = true;
2537 for (unsigned i=0;i<RT_ELEMENTS(pVM->csam.s.pvCallInstruction);i++)
2539 RTRCPTR pHandler = pVM->csam.s.pvCallInstruction[i];
2548 STAM_PROFILE_START(&pVM->csam.s.StatTime, a);
2549 rc = csamAnalyseCodeStream(pVM, pHandler, pHandler, true, CSAMR3AnalyseCallback, pPage, &cacheRec);
2550 STAM_PROFILE_STOP(&pVM->csam.s.StatTime, a);
2552 PGMPhysReleasePageMappingLock(pVM, &cacheRec.Lock);
2575 STAM_PROFILE_START(&pVM->csam.s.StatCheckGates, a);
2584 STAM_PROFILE_STOP(&pVM->csam.s.StatCheckGates, a);
2591 Assert(TRPMR3GetGuestTrapHandler(pVM, iGate) == TRPM_INVALID_HANDLER);
2605 pHandler = SELMToFlatBySel(pVM, pGuestIdte->Gen.u16SegSel, pHandler);
2607 rc = SELMR3GetSelectorInfo(pVM, pVCpu, pGuestIdte->Gen.u16SegSel, &selInfo);
2629 STAM_PROFILE_START(&pVM->csam.s.StatTime, b);
2630 rc = csamAnalyseCodeStream(pVM, pHandler, pHandler, true, CSAMR3AnalyseCallback, pPage, &cacheRec);
2631 STAM_PROFILE_STOP(&pVM->csam.s.StatTime, b);
2633 PGMPhysReleasePageMappingLock(pVM, &cacheRec.Lock);
2653 rc = CPUMR3DisasmInstrCPU(pVM, pVCpu, pCtx, pHandler - aOpenBsdPushCSOffset[i], &cpu, NULL);
2658 rc = PATMR3InstallPatch(pVM, pHandler - aOpenBsdPushCSOffset[i], PATMFL_CODE32 | PATMFL_GUEST_SPECIFIC);
2690 rc = PATMR3InstallPatch(pVM, pHandler, fPatchFlags);
2696 RTRCPTR pNewHandlerGC = PATMR3QueryPatchGCPtr(pVM, pHandler);
2699 rc = TRPMR3SetGuestTrapHandler(pVM, iGate, pNewHandlerGC);
2706 STAM_PROFILE_STOP(&pVM->csam.s.StatCheckGates, a);
2715 * @param pVM Pointer to the VM.
2718 VMMR3DECL(int) CSAMR3RecordCallAddress(PVM pVM, RTRCPTR GCPtrCall)
2720 Assert(!HMIsEnabled(pVM));
2721 for (unsigned i=0;i<RT_ELEMENTS(pVM->csam.s.pvCallInstruction);i++)
2723 if (pVM->csam.s.pvCallInstruction[i] == GCPtrCall)
2729 pVM->csam.s.pvCallInstruction[pVM->csam.s.iCallInstruction++] = GCPtrCall;
2730 if (pVM->csam.s.iCallInstruction >= RT_ELEMENTS(pVM->csam.s.pvCallInstruction))
2731 pVM->csam.s.iCallInstruction = 0;
2746 PVM pVM = pUVM->pVM;
2747 VM_ASSERT_VALID_EXT_RETURN(pVM, false);
2748 return CSAMIsEnabled(pVM);
2762 PVM pVM = pUVM->pVM;
2763 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
2765 if (HMIsEnabled(pVM))
2767 Assert(!pVM->fCSAMEnabled);
2773 rc = CSAMEnableScanning(pVM);
2775 rc = CSAMDisableScanning(pVM);