/** * Relocate the queues. * * @param pVM Pointer to the VM. * @param offDelta The relocation delta. */ void pdmR3QueueRelocate(PVM pVM, RTGCINTPTR offDelta) { /* * Process the queues. */ PUVM pUVM = pVM->pUVM; PPDMQUEUE pQueueNext = pUVM->pdm.s.pQueuesTimer; PPDMQUEUE pQueue = pUVM->pdm.s.pQueuesForced; do { while (pQueue) { if (pQueue->pVMRC) { pQueue->pVMRC = pVM->pVMRC; /* Pending RC items. */ if (pQueue->pPendingRC) { pQueue->pPendingRC += offDelta; PPDMQUEUEITEMCORE pCur = (PPDMQUEUEITEMCORE)MMHyperRCToR3(pVM, pQueue->pPendingRC); while (pCur->pNextRC) { pCur->pNextRC += offDelta; pCur = (PPDMQUEUEITEMCORE)MMHyperRCToR3(pVM, pCur->pNextRC); } } /* The free items. */ uint32_t i = pQueue->iFreeTail; while (i != pQueue->iFreeHead) { pQueue->aFreeItems[i].pItemRC = MMHyperR3ToRC(pVM, pQueue->aFreeItems[i].pItemR3); i = (i + 1) % (pQueue->cItems + PDMQUEUE_FREE_SLACK); } } /* next queue */ pQueue = pQueue->pNext; } /* next queue list */ pQueue = pQueueNext; pQueueNext = NULL; } while (pQueue); }
/** * 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; }
/** * 'Allocate' selectors for 32-bit code/data in rings 0-3. * * 0060 - r0 code * 0068 - r0 data * * 1060 - r1 code * 1068 - r1 data * * 2060 - r2 code * 2068 - r2 data * * 3060 - r3 code * 3068 - r3 data * */ static void SetupSelectors(PVM pVM) { /* * Find the GDT - This is a HACK :-) */ RTRCPTR RCPtr = CPUMGetHyperGDTR(VMMGetCpu0(pVM), NULL); PX86DESC paGDTEs = (PX86DESC)MMHyperRCToR3(pVM, RCPtr); for (unsigned i = 0; i <= 3; i++) { RTSEL Sel = (i << 12) + 0x60; /* 32-bit code selector. */ PX86DESC pGDTE = &paGDTEs[Sel >> X86_SEL_SHIFT]; pGDTE->au32[0] = pGDTE->au32[1] = 0; pGDTE->Gen.u16LimitLow = 0xffff; pGDTE->Gen.u4LimitHigh = 0xf; pGDTE->Gen.u1Granularity= 1; pGDTE->Gen.u1Present = 1; pGDTE->Gen.u2Dpl = i; pGDTE->Gen.u1DefBig = 1; pGDTE->Gen.u1DescType = 1; /* !system */ pGDTE->Gen.u4Type = X86_SEL_TYPE_ER_ACC; /* 32-bit data selector. */ pGDTE++; pGDTE->au32[0] = pGDTE->au32[1] = 0; pGDTE->Gen.u16LimitLow = 0xffff; pGDTE->Gen.u4LimitHigh = 0xf; pGDTE->Gen.u1Granularity= 1; pGDTE->Gen.u1Present = 1; pGDTE->Gen.u2Dpl = i; pGDTE->Gen.u1DefBig = 1; pGDTE->Gen.u1DescType = 1; /* !system */ pGDTE->Gen.u4Type = X86_SEL_TYPE_RW_ACC; } }
/** * Process pending items in one queue. * * @returns Success indicator. * If false the item the consumer said "enough!". * @param pQueue The queue. */ static bool pdmR3QueueFlush(PPDMQUEUE pQueue) { STAM_PROFILE_START(&pQueue->StatFlushPrf,p); /* * Get the lists. */ PPDMQUEUEITEMCORE pItems = ASMAtomicXchgPtrT(&pQueue->pPendingR3, NULL, PPDMQUEUEITEMCORE); RTRCPTR pItemsRC = ASMAtomicXchgRCPtr(&pQueue->pPendingRC, NIL_RTRCPTR); RTR0PTR pItemsR0 = ASMAtomicXchgR0Ptr(&pQueue->pPendingR0, NIL_RTR0PTR); AssertMsgReturn( pItemsR0 || pItemsRC || pItems, ("Someone is racing us? This shouldn't happen!\n"), true); /* * Reverse the list (it's inserted in LIFO order to avoid semaphores, remember). */ PPDMQUEUEITEMCORE pCur = pItems; pItems = NULL; while (pCur) { PPDMQUEUEITEMCORE pInsert = pCur; pCur = pCur->pNextR3; pInsert->pNextR3 = pItems; pItems = pInsert; } /* * Do the same for any pending RC items. */ while (pItemsRC) { PPDMQUEUEITEMCORE pInsert = (PPDMQUEUEITEMCORE)MMHyperRCToR3(pQueue->pVMR3, pItemsRC); pItemsRC = pInsert->pNextRC; pInsert->pNextRC = NIL_RTRCPTR; pInsert->pNextR3 = pItems; pItems = pInsert; } /* * Do the same for any pending R0 items. */ while (pItemsR0) { PPDMQUEUEITEMCORE pInsert = (PPDMQUEUEITEMCORE)MMHyperR0ToR3(pQueue->pVMR3, pItemsR0); pItemsR0 = pInsert->pNextR0; pInsert->pNextR0 = NIL_RTR0PTR; pInsert->pNextR3 = pItems; pItems = pInsert; } /* * Feed the items to the consumer function. */ Log2(("pdmR3QueueFlush: pQueue=%p enmType=%d pItems=%p\n", pQueue, pQueue->enmType, pItems)); switch (pQueue->enmType) { case PDMQUEUETYPE_DEV: while (pItems) { if (!pQueue->u.Dev.pfnCallback(pQueue->u.Dev.pDevIns, pItems)) break; pCur = pItems; pItems = pItems->pNextR3; pdmR3QueueFreeItem(pQueue, pCur); } break; case PDMQUEUETYPE_DRV: while (pItems) { if (!pQueue->u.Drv.pfnCallback(pQueue->u.Drv.pDrvIns, pItems)) break; pCur = pItems; pItems = pItems->pNextR3; pdmR3QueueFreeItem(pQueue, pCur); } break; case PDMQUEUETYPE_INTERNAL: while (pItems) { if (!pQueue->u.Int.pfnCallback(pQueue->pVMR3, pItems)) break; pCur = pItems; pItems = pItems->pNextR3; pdmR3QueueFreeItem(pQueue, pCur); } break; case PDMQUEUETYPE_EXTERNAL: while (pItems) { if (!pQueue->u.Ext.pfnCallback(pQueue->u.Ext.pvUser, pItems)) break; pCur = pItems; pItems = pItems->pNextR3; pdmR3QueueFreeItem(pQueue, pCur); } break; default: AssertMsgFailed(("Invalid queue type %d\n", pQueue->enmType)); break; } /* * Success? */ if (pItems) { /* * Reverse the list. */ pCur = pItems; pItems = NULL; while (pCur) { PPDMQUEUEITEMCORE pInsert = pCur; pCur = pInsert->pNextR3; pInsert->pNextR3 = pItems; pItems = pInsert; } /* * Insert the list at the tail of the pending list. */ for (;;) { if (ASMAtomicCmpXchgPtr(&pQueue->pPendingR3, pItems, NULL)) break; PPDMQUEUEITEMCORE pPending = ASMAtomicXchgPtrT(&pQueue->pPendingR3, NULL, PPDMQUEUEITEMCORE); if (pPending) { pCur = pPending; while (pCur->pNextR3) pCur = pCur->pNextR3; pCur->pNextR3 = pItems; pItems = pPending; } } STAM_REL_COUNTER_INC(&pQueue->StatFlushLeftovers); STAM_PROFILE_STOP(&pQueue->StatFlushPrf,p); return false; } STAM_PROFILE_STOP(&pQueue->StatFlushPrf,p); return true; }