- Timestamp:
- Jan 31, 2012 2:55:13 PM (13 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/gmm.h
r39917 r39920 617 617 { 618 618 /** Region base address. */ 619 RTGCPTR64 GCRegionAddr;619 RTGCPTR64 GCRegionAddr; 620 620 /** Region size. */ 621 uint32_t cbRegion;621 uint32_t cbRegion; 622 622 /** Alignment. */ 623 uint32_t u32Alignment;624 /** Pointer to physical page idarray. */625 uint32_t *paHCPhysPageID;623 uint32_t u32Alignment; 624 /** Pointer to physical GMM page ID array. */ 625 uint32_t *paidPages; 626 626 } GMMSHAREDREGIONDESC; 627 627 /** Pointer to a GMMSHAREDREGIONDESC. */ … … 664 664 RTGCPHYS GCPhys; 665 665 /** GMM page id. (in/out) */ 666 uint32_t uHCPhysPageId;666 uint32_t idPage; 667 667 /** Align at 8 byte boundary. */ 668 668 uint32_t uAlignment; … … 671 671 typedef GMMSHAREDPAGEDESC *PGMMSHAREDPAGEDESC; 672 672 673 GMMR0DECL(int) GMMR0SharedModuleCheckPage(PGVM pGVM, PGMMSHAREDMODULE pModule, unsigned idxRegion, unsigned idxPage, PGMMSHAREDPAGEDESC pPageDesc); 673 GMMR0DECL(int) GMMR0SharedModuleCheckPage(PGVM pGVM, PGMMSHAREDMODULE pModule, unsigned idxRegion, unsigned idxPage, 674 PGMMSHAREDPAGEDESC pPageDesc); 674 675 675 676 /** -
trunk/src/VBox/VMM/VMMR0/GMMR0.cpp
r39917 r39920 4217 4217 for (unsigned i = 0; i < cRegions; i++) 4218 4218 { 4219 pRecVM->aRegions[i].GCRegionAddr 4220 pRecVM->aRegions[i].cbRegion 4221 pRecVM->aRegions[i].u32Alignment 4222 pRecVM->aRegions[i].pa HCPhysPageID= NULL; /* unused */4219 pRecVM->aRegions[i].GCRegionAddr = pRegions[i].GCRegionAddr; 4220 pRecVM->aRegions[i].cbRegion = RT_ALIGN_T(pRegions[i].cbRegion, PAGE_SIZE, uint32_t); 4221 pRecVM->aRegions[i].u32Alignment = 0; 4222 pRecVM->aRegions[i].paidPages = NULL; /* unused */ 4223 4223 } 4224 4224 … … 4283 4283 { 4284 4284 Log(("New region %d base=%RGv size %x\n", i, pRegions[i].GCRegionAddr, pRegions[i].cbRegion)); 4285 pGlobalModule->aRegions[i].GCRegionAddr 4286 pGlobalModule->aRegions[i].cbRegion 4287 pGlobalModule->aRegions[i].u32Alignment 4288 pGlobalModule->aRegions[i].pa HCPhysPageID= NULL; /* uninitialized. */4285 pGlobalModule->aRegions[i].GCRegionAddr = pRegions[i].GCRegionAddr; 4286 pGlobalModule->aRegions[i].cbRegion = RT_ALIGN_T(pRegions[i].cbRegion, PAGE_SIZE, uint32_t); 4287 pGlobalModule->aRegions[i].u32Alignment = 0; 4288 pGlobalModule->aRegions[i].paidPages = NULL; /* uninitialized. */ 4289 4289 } 4290 4290 … … 4418 4418 if (pRec->cUsers == 0) 4419 4419 { 4420 /* Free the ranges, but leave the pages intact as there might still be references; they will be cleared by the COW mechanism. */ 4421 for (unsigned i = 0; i < pRec->cRegions; i++) 4422 if (pRec->aRegions[i].paHCPhysPageID) 4423 RTMemFree(pRec->aRegions[i].paHCPhysPageID); 4420 /* Free the ranges, but leave the pages intact as there 4421 might still be references; they will be cleared by 4422 the COW mechanism. */ 4423 for (uint32_t i = 0; i < pRec->cRegions; i++) 4424 { 4425 RTMemFree(pRec->aRegions[i].paidPages); 4426 pRec->aRegions[i].paidPages = NULL; 4427 } 4424 4428 4425 4429 Assert(pRec->Core.Key == GCBaseAddr || pRec->enmGuestOS == VBOXOSFAMILY_Windows64); 4426 4430 Assert(pRec->cRegions == pRecVM->cRegions); 4427 4431 #ifdef VBOX_STRICT 4428 for (u nsignedi = 0; i < pRecVM->cRegions; i++)4432 for (uint32_t i = 0; i < pRecVM->cRegions; i++) 4429 4433 { 4430 4434 Assert(pRecVM->aRegions[i].GCRegionAddr == pRec->aRegions[i].GCRegionAddr); … … 4540 4544 4541 4545 4546 static int gmmR0SharedModuleCheckPageFirstTime(PGMM pGMM, PGVM pGVM, PGMMSHAREDMODULE pModule, 4547 unsigned idxRegion, unsigned idxPage, 4548 PGMMSHAREDPAGEDESC pPageDesc, PGMMSHAREDREGIONDESC pGlobalRegion) 4549 { 4550 /* Easy case: just change the internal page type. */ 4551 PGMMPAGE pPage = gmmR0GetPage(pGMM, pPageDesc->idPage); 4552 AssertMsgReturn(pPage, ("idPage=%#x (GCPhys=%RGp HCPhys=%RHp idxRegion=%#x idxPage=%#x) #1\n", 4553 pPageDesc->idPage, pPageDesc->GCPhys, pPageDesc->HCPhys, idxRegion, idxPage), 4554 VERR_PGM_PHYS_INVALID_PAGE_ID); 4555 4556 AssertMsg(pPageDesc->GCPhys == (pPage->Private.pfn << 12), ("desc %RGp gmm %RGp\n", pPageDesc->HCPhys, (pPage->Private.pfn << 12))); 4557 4558 gmmR0ConvertToSharedPage(pGMM, pGVM, pPageDesc->HCPhys, pPageDesc->idPage, pPage); 4559 4560 /* Keep track of these references. */ 4561 pGlobalRegion->paidPages[idxPage] = pPageDesc->idPage; 4562 4563 return VINF_SUCCESS; 4564 } 4565 4542 4566 /** 4543 4567 * Checks specified shared module range for changes … … 4563 4587 PGMMSHAREDPAGEDESC pPageDesc) 4564 4588 { 4565 int rc = VINF_SUCCESS;4589 int rc; 4566 4590 PGMM pGMM; 4567 4591 GMM_GET_VALID_INSTANCE(pGMM, VERR_GMM_INSTANCE); 4568 unsigned cPages = pModule->aRegions[idxRegion].cbRegion >> PAGE_SHIFT; 4569 4570 AssertReturn(idxRegion < pModule->cRegions, VERR_INVALID_PARAMETER); 4571 AssertReturn(idxPage < cPages, VERR_INVALID_PARAMETER); 4592 4593 AssertMsgReturn(idxRegion < pModule->cRegions, 4594 ("idxRegion=%#x cRegions=%#x %s %s\n", idxRegion, pModule->cRegions, pModule->szName, pModule->szVersion), 4595 VERR_INVALID_PARAMETER); 4596 4597 unsigned const cPages = pModule->aRegions[idxRegion].cbRegion >> PAGE_SHIFT; 4598 AssertMsgReturn(idxPage < cPages, 4599 ("idxRegion=%#x cRegions=%#x %s %s\n", idxRegion, pModule->cRegions, pModule->szName, pModule->szVersion), 4600 VERR_INVALID_PARAMETER); 4572 4601 4573 4602 LogFlow(("GMMR0SharedModuleCheckRange %s base %RGv region %d idxPage %d\n", pModule->szName, pModule->Core.Key, idxRegion, idxPage)); 4574 4603 4604 /* 4605 * First time; create a page descriptor array. 4606 */ 4575 4607 PGMMSHAREDREGIONDESC pGlobalRegion = &pModule->aRegions[idxRegion]; 4576 if (!pGlobalRegion->paHCPhysPageID) 4577 { 4578 /* First time; create a page descriptor array. */ 4608 if (!pGlobalRegion->paidPages) 4609 { 4579 4610 Log(("Allocate page descriptor array for %d pages\n", cPages)); 4580 pGlobalRegion->paHCPhysPageID = (uint32_t *)RTMemAlloc(cPages * sizeof(*pGlobalRegion->paHCPhysPageID)); 4581 if (!pGlobalRegion->paHCPhysPageID) 4582 { 4583 AssertFailed(); 4584 rc = VERR_NO_MEMORY; 4585 goto end; 4586 } 4611 pGlobalRegion->paidPages = (uint32_t *)RTMemAlloc(cPages * sizeof(pGlobalRegion->paidPages[0])); 4612 AssertReturn(pGlobalRegion->paidPages, VERR_NO_MEMORY); 4613 4587 4614 /* Invalidate all descriptors. */ 4588 4615 for (unsigned i = 0; i < cPages; i++) 4589 pGlobalRegion->paHCPhysPageID[i] = NIL_GMM_PAGEID; 4590 } 4591 4592 /* We've seen this shared page for the first time? */ 4593 if (pGlobalRegion->paHCPhysPageID[idxPage] == NIL_GMM_PAGEID) 4594 { 4595 new_shared_page: 4616 pGlobalRegion->paidPages[i] = NIL_GMM_PAGEID; 4617 } 4618 4619 /* 4620 * We've seen this shared page for the first time? 4621 */ 4622 if (pGlobalRegion->paidPages[idxPage] == NIL_GMM_PAGEID) 4623 { 4596 4624 Log(("New shared page guest %RGp host %RHp\n", pPageDesc->GCPhys, pPageDesc->HCPhys)); 4597 4598 /* Easy case: just change the internal page type. */ 4599 PGMMPAGE pPage = gmmR0GetPage(pGMM, pPageDesc->uHCPhysPageId); 4600 if (!pPage) 4601 { 4602 Log(("GMMR0SharedModuleCheckPage: Invalid idPage=%#x #1 (GCPhys=%RGp HCPhys=%RHp idxRegion=%#x idxPage=%#x)\n", 4603 pPageDesc->uHCPhysPageId, pPageDesc->GCPhys, pPageDesc->HCPhys, idxRegion, idxPage)); 4604 AssertFailed(); 4605 rc = VERR_PGM_PHYS_INVALID_PAGE_ID; 4606 goto end; 4607 } 4608 4609 AssertMsg(pPageDesc->GCPhys == (pPage->Private.pfn << 12), ("desc %RGp gmm %RGp\n", pPageDesc->HCPhys, (pPage->Private.pfn << 12))); 4610 4611 gmmR0ConvertToSharedPage(pGMM, pGVM, pPageDesc->HCPhys, pPageDesc->uHCPhysPageId, pPage); 4612 4613 /* Keep track of these references. */ 4614 pGlobalRegion->paHCPhysPageID[idxPage] = pPageDesc->uHCPhysPageId; 4615 } 4616 else 4617 { 4618 uint8_t *pbLocalPage, *pbSharedPage; 4619 uint8_t *pbChunk; 4620 PGMMCHUNK pChunk; 4621 4622 Assert(pPageDesc->uHCPhysPageId != pGlobalRegion->paHCPhysPageID[idxPage]); 4623 4624 Log(("Replace existing page guest %RGp host %RHp id %x -> id %x\n", pPageDesc->GCPhys, pPageDesc->HCPhys, pPageDesc->uHCPhysPageId, pGlobalRegion->paHCPhysPageID[idxPage])); 4625 4626 /* Get the shared page source. */ 4627 PGMMPAGE pPage = gmmR0GetPage(pGMM, pGlobalRegion->paHCPhysPageID[idxPage]); 4628 if (!pPage) 4629 { 4630 Log(("GMMR0SharedModuleCheckPage: Invalid idPage=%#x #2 (idxRegion=%#x idxPage=%#x)\n", 4631 pPageDesc->uHCPhysPageId, idxRegion, idxPage)); 4632 AssertFailed(); 4633 rc = VERR_PGM_PHYS_INVALID_PAGE_ID; 4634 goto end; 4635 } 4636 if (pPage->Common.u2State != GMM_PAGE_STATE_SHARED) 4637 { 4638 /* Page was freed at some point; invalidate this entry. */ 4639 /** @todo this isn't really bullet proof. */ 4640 Log(("Old shared page was freed -> create a new one\n")); 4641 pGlobalRegion->paHCPhysPageID[idxPage] = NIL_GMM_PAGEID; 4642 goto new_shared_page; /* ugly goto */ 4643 } 4644 4645 Log(("Replace existing page guest host %RHp -> %RHp\n", pPageDesc->HCPhys, ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT)); 4646 4647 /* Calculate the virtual address of the local page. */ 4648 pChunk = gmmR0GetChunk(pGMM, pPageDesc->uHCPhysPageId >> GMM_CHUNKID_SHIFT); 4649 if (pChunk) 4650 { 4651 if (!gmmR0IsChunkMapped(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk)) 4652 { 4653 Log(("GMMR0SharedModuleCheckPage: Invalid idPage=%#x #3\n", pPageDesc->uHCPhysPageId)); 4654 AssertFailed(); 4655 rc = VERR_PGM_PHYS_INVALID_PAGE_ID; 4656 goto end; 4657 } 4658 pbLocalPage = pbChunk + ((pPageDesc->uHCPhysPageId & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT); 4659 } 4660 else 4661 { 4662 Log(("GMMR0SharedModuleCheckPage: Invalid idPage=%#x #4\n", pPageDesc->uHCPhysPageId)); 4663 AssertFailed(); 4664 rc = VERR_PGM_PHYS_INVALID_PAGE_ID; 4665 goto end; 4666 } 4667 4668 /* Calculate the virtual address of the shared page. */ 4669 pChunk = gmmR0GetChunk(pGMM, pGlobalRegion->paHCPhysPageID[idxPage] >> GMM_CHUNKID_SHIFT); 4670 Assert(pChunk); /* can't fail as gmmR0GetPage succeeded. */ 4671 4672 /* Get the virtual address of the physical page; map the chunk into the VM process if not already done. */ 4673 if (!gmmR0IsChunkMapped(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk)) 4674 { 4675 Log(("Map chunk into process!\n")); 4676 rc = gmmR0MapChunk(pGMM, pGVM, pChunk, false /*fRelaxedSem*/, (PRTR3PTR)&pbChunk); 4677 if (rc != VINF_SUCCESS) 4678 { 4679 AssertRC(rc); 4680 goto end; 4681 } 4682 } 4683 pbSharedPage = pbChunk + ((pGlobalRegion->paHCPhysPageID[idxPage] & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT); 4684 4685 /** @todo write ASMMemComparePage. */ 4686 if (memcmp(pbSharedPage, pbLocalPage, PAGE_SIZE)) 4687 { 4688 Log(("Unexpected differences found between local and shared page; skip\n")); 4689 /* Signal to the caller that this one hasn't changed. */ 4690 pPageDesc->uHCPhysPageId = NIL_GMM_PAGEID; 4691 goto end; 4692 } 4693 4694 /* Free the old local page. */ 4695 GMMFREEPAGEDESC PageDesc; 4696 4697 PageDesc.idPage = pPageDesc->uHCPhysPageId; 4698 rc = gmmR0FreePages(pGMM, pGVM, 1, &PageDesc, GMMACCOUNT_BASE); 4625 return gmmR0SharedModuleCheckPageFirstTime(pGMM, pGVM, pModule, idxRegion, idxPage, pPageDesc, pGlobalRegion); 4626 } 4627 4628 /* 4629 * We've seen it before... 4630 */ 4631 Log(("Replace existing page guest %RGp host %RHp id %#x -> id %#x\n", 4632 pPageDesc->GCPhys, pPageDesc->HCPhys, pPageDesc->idPage, pGlobalRegion->paidPages[idxPage])); 4633 Assert(pPageDesc->idPage != pGlobalRegion->paidPages[idxPage]); 4634 4635 /* 4636 * Get the shared page source. 4637 */ 4638 PGMMPAGE pPage = gmmR0GetPage(pGMM, pGlobalRegion->paidPages[idxPage]); 4639 AssertMsgReturn(pPage, ("idPage=%#x (idxRegion=%#x idxPage=%#x) #2\n", pPageDesc->idPage, idxRegion, idxPage), 4640 VERR_PGM_PHYS_INVALID_PAGE_ID); 4641 4642 if (pPage->Common.u2State != GMM_PAGE_STATE_SHARED) 4643 { 4644 /* 4645 * Page was freed at some point; invalidate this entry. 4646 */ 4647 /** @todo this isn't really bullet proof. */ 4648 Log(("Old shared page was freed -> create a new one\n")); 4649 pGlobalRegion->paidPages[idxPage] = NIL_GMM_PAGEID; 4650 return gmmR0SharedModuleCheckPageFirstTime(pGMM, pGVM, pModule, idxRegion, idxPage, pPageDesc, pGlobalRegion); 4651 } 4652 4653 Log(("Replace existing page guest host %RHp -> %RHp\n", pPageDesc->HCPhys, ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT)); 4654 4655 /* 4656 * Calculate the virtual address of the local page. 4657 */ 4658 PGMMCHUNK pChunk = gmmR0GetChunk(pGMM, pPageDesc->idPage >> GMM_CHUNKID_SHIFT); 4659 AssertMsgReturn(pChunk, ("idPage=%#x (idxRegion=%#x idxPage=%#x) #4\n", pPageDesc->idPage, idxRegion, idxPage), 4660 VERR_PGM_PHYS_INVALID_PAGE_ID); 4661 4662 uint8_t *pbChunk; 4663 AssertMsgReturn(gmmR0IsChunkMapped(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk), 4664 ("idPage=%#x (idxRegion=%#x idxPage=%#x) #3\n", pPageDesc->idPage, idxRegion, idxPage), 4665 VERR_PGM_PHYS_INVALID_PAGE_ID); 4666 uint8_t *pbLocalPage = pbChunk + ((pPageDesc->idPage & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT); 4667 4668 /* 4669 * Calculate the virtual address of the shared page. 4670 */ 4671 pChunk = gmmR0GetChunk(pGMM, pGlobalRegion->paidPages[idxPage] >> GMM_CHUNKID_SHIFT); 4672 Assert(pChunk); /* can't fail as gmmR0GetPage succeeded. */ 4673 4674 /* 4675 * Get the virtual address of the physical page; map the chunk into the VM 4676 * process if not already done. 4677 */ 4678 if (!gmmR0IsChunkMapped(pGMM, pGVM, pChunk, (PRTR3PTR)&pbChunk)) 4679 { 4680 Log(("Map chunk into process!\n")); 4681 rc = gmmR0MapChunk(pGMM, pGVM, pChunk, false /*fRelaxedSem*/, (PRTR3PTR)&pbChunk); 4699 4682 AssertRCReturn(rc, rc); 4700 4701 gmmR0UseSharedPage(pGMM, pGVM, pPage); 4702 4703 /* Pass along the new physical address & page id. */ 4704 pPageDesc->HCPhys = ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT; 4705 pPageDesc->uHCPhysPageId = pGlobalRegion->paHCPhysPageID[idxPage]; 4706 } 4707 end: 4708 return rc; 4683 } 4684 uint8_t *pbSharedPage = pbChunk + ((pGlobalRegion->paidPages[idxPage] & GMM_PAGEID_IDX_MASK) << PAGE_SHIFT); 4685 4686 /** @todo write ASMMemComparePage. */ 4687 if (memcmp(pbSharedPage, pbLocalPage, PAGE_SIZE)) 4688 { 4689 Log(("Unexpected differences found between local and shared page; skip\n")); 4690 /* Signal to the caller that this one hasn't changed. */ 4691 pPageDesc->idPage = NIL_GMM_PAGEID; 4692 return VINF_SUCCESS; 4693 } 4694 4695 /* 4696 * Free the old local page. 4697 */ 4698 GMMFREEPAGEDESC PageDesc; 4699 PageDesc.idPage = pPageDesc->idPage; 4700 rc = gmmR0FreePages(pGMM, pGVM, 1, &PageDesc, GMMACCOUNT_BASE); 4701 AssertRCReturn(rc, rc); 4702 4703 gmmR0UseSharedPage(pGMM, pGVM, pPage); 4704 4705 /* 4706 * Pass along the new physical address & page id. 4707 */ 4708 pPageDesc->HCPhys = ((uint64_t)pPage->Shared.pfn) << PAGE_SHIFT; 4709 pPageDesc->idPage = pGlobalRegion->paidPages[idxPage]; 4710 4711 return VINF_SUCCESS; 4709 4712 } 4710 4713 … … 4734 4737 { 4735 4738 for (uint32_t i = 0; i < pRec->cRegions; i++) 4736 if (pRec->aRegions[i].paHCPhysPageID) 4737 RTMemFree(pRec->aRegions[i].paHCPhysPageID); 4739 { 4740 RTMemFree(pRec->aRegions[i].paidPages); 4741 pRec->aRegions[i].paidPages = NULL; 4742 } 4738 4743 4739 4744 /* Remove from the tree and free memory. */ -
trunk/src/VBox/VMM/VMMR0/PGMR0SharedPage.cpp
r39909 r39920 81 81 && PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED) 82 82 { 83 PageDesc. uHCPhysPageId= PGM_PAGE_GET_PAGEID(pPage);84 PageDesc.HCPhys 85 PageDesc.GCPhys 83 PageDesc.idPage = PGM_PAGE_GET_PAGEID(pPage); 84 PageDesc.HCPhys = PGM_PAGE_GET_HCPHYS(pPage); 85 PageDesc.GCPhys = GCPhys; 86 86 87 87 rc = GMMR0SharedModuleCheckPage(pGVM, pModule, idxRegion, idxPage, &PageDesc); … … 89 89 { 90 90 /* Any change for this page? */ 91 if (PageDesc. uHCPhysPageId!= NIL_GMM_PAGEID)91 if (PageDesc.idPage != NIL_GMM_PAGEID) 92 92 { 93 93 Assert(PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED); … … 106 106 /* Update the physical address and page id now. */ 107 107 PGM_PAGE_SET_HCPHYS(pVM, pPage, PageDesc.HCPhys); 108 PGM_PAGE_SET_PAGEID(pVM, pPage, PageDesc. uHCPhysPageId);108 PGM_PAGE_SET_PAGEID(pVM, pPage, PageDesc.idPage); 109 109 110 110 /* Invalidate page map TLB entry for this page too. */
Note:
See TracChangeset
for help on using the changeset viewer.