/** * Returns the current code scanner enabled flag. * * @returns COM status code * @param enabled address of result variable */ STDMETHODIMP MachineDebugger::COMGETTER(CSAMEnabled)(BOOL *enabled) { if (!enabled) return E_POINTER; if (gpVM) *enabled = CSAMIsEnabled(gpVM); else *enabled = false; return S_OK; }
/** * Mark a page as scanned/not scanned * * @note: we always mark it as scanned, even if we haven't completely done so * * @returns VBox status code. * @param pVM Pointer to the VM. * @param pPage GC page address (not necessarily aligned) * @param fScanned Mark as scanned or not scanned * */ VMM_INT_DECL(int) CSAMMarkPage(PVM pVM, RTRCUINTPTR pPage, bool fScanned) { int pgdir, bit; uintptr_t page; #ifdef LOG_ENABLED if (fScanned && !CSAMIsPageScanned(pVM, (RTRCPTR)pPage)) Log(("CSAMMarkPage %RRv\n", pPage)); #endif if (!CSAMIsEnabled(pVM)) return VINF_SUCCESS; Assert(!HMIsEnabled(pVM)); page = (uintptr_t)pPage; pgdir = page >> X86_PAGE_4M_SHIFT; bit = (page & X86_PAGE_4M_OFFSET_MASK) >> X86_PAGE_4K_SHIFT; Assert(pgdir < CSAM_PGDIRBMP_CHUNKS); Assert(bit < PAGE_SIZE); if(!CTXSUFF(pVM->csam.s.pPDBitmap)[pgdir]) { STAM_COUNTER_INC(&pVM->csam.s.StatBitmapAlloc); int rc = MMHyperAlloc(pVM, CSAM_PAGE_BITMAP_SIZE, 0, MM_TAG_CSAM, (void **)&pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir]); if (RT_FAILURE(rc)) { Log(("MMHyperAlloc failed with %Rrc\n", rc)); return rc; } #ifdef IN_RC pVM->csam.s.pPDHCBitmapGC[pgdir] = MMHyperRCToR3(pVM, (RCPTRTYPE(void*))pVM->csam.s.pPDBitmapGC[pgdir]); if (!pVM->csam.s.pPDHCBitmapGC[pgdir]) { Log(("MMHyperHC2GC failed for %RRv\n", pVM->csam.s.pPDBitmapGC[pgdir])); return rc; } #else pVM->csam.s.pPDGCBitmapHC[pgdir] = MMHyperR3ToRC(pVM, pVM->csam.s.pPDBitmapHC[pgdir]); if (!pVM->csam.s.pPDGCBitmapHC[pgdir]) { Log(("MMHyperHC2GC failed for %RHv\n", pVM->csam.s.pPDBitmapHC[pgdir])); return rc; } #endif } if(fScanned) ASMBitSet((void *)pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir], bit); else ASMBitClear((void *)pVM->csam.s.CTXSUFF(pPDBitmap)[pgdir], bit); return VINF_SUCCESS; }
/** * Check if this page needs to be analysed by CSAM. * * This function should only be called for supervisor pages and * only when CSAM is enabled. Leaving these selection criteria * to the caller simplifies the interface (PTE passing). * * Note that the page has not yet been synced, so the TLB trick * (which wasn't ever active anyway) cannot be applied. * * @returns true if the page should be marked not present because * CSAM want need to scan it. * @returns false if the page was already scanned. * @param pVM Pointer to the VM. * @param GCPtr GC pointer of page */ VMM_INT_DECL(bool) CSAMDoesPageNeedScanning(PVM pVM, RTRCUINTPTR GCPtr) { if(!CSAMIsEnabled(pVM)) return false; if(CSAMIsPageScanned(pVM, (RTRCPTR)GCPtr)) { /* Already checked! */ STAM_COUNTER_ADD(&CTXSUFF(pVM->csam.s.StatNrKnownPages), 1); return false; } STAM_COUNTER_ADD(&CTXSUFF(pVM->csam.s.StatNrPageNP), 1); return true; }
/** * Check if this page needs to be analysed by CSAM * * @returns VBox status code * @param pVM Pointer to the VM. * @param pvFault Fault address */ VMM_INT_DECL(int) CSAMExecFault(PVM pVM, RTRCPTR pvFault) { if(!CSAMIsEnabled(pVM)) return VINF_SUCCESS; LogFlow(("CSAMGCExecFault: for page %08X scanned=%d\n", pvFault, CSAMIsPageScanned(pVM, pvFault))); if(CSAMIsPageScanned(pVM, pvFault)) { // Already checked! STAM_COUNTER_ADD(&pVM->csam.s.StatNrKnownPagesGC, 1); return VINF_SUCCESS; } STAM_COUNTER_ADD(&pVM->csam.s.StatNrTraps, 1); VMCPU_FF_SET(VMMGetCpu0(pVM), VMCPU_FF_CSAM_SCAN_PAGE); return VINF_CSAM_PENDING_ACTION; }
/** * Returns the current code scanner enabled flag. * * @returns COM status code * @param aEnabled address of result variable */ STDMETHODIMP MachineDebugger::COMGETTER(CSAMEnabled) (BOOL *aEnabled) { CheckComArgOutPointerValid(aEnabled); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); Console::SafeVMPtrQuiet pVM (mParent); if (pVM.isOk()) *aEnabled = CSAMIsEnabled (pVM.raw()); else *aEnabled = false; return S_OK; }