Changeset 29424 in vbox for trunk/src/VBox/VMM/PGMSharedPage.cpp
- Timestamp:
- May 12, 2010 3:11:09 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 61539
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PGMSharedPage.cpp
r29411 r29424 35 35 #include <iprt/mem.h> 36 36 37 38 #ifdef VBOX_WITH_PAGE_SHARING39 /**40 * Rendezvous callback that will be called once.41 *42 * @returns VBox strict status code.43 * @param pVM VM handle.44 * @param pVCpu The VMCPU handle for the calling EMT.45 * @param pvUser PGMMREGISTERSHAREDMODULEREQ46 */47 static DECLCALLBACK(VBOXSTRICTRC) pgmR3SharedModuleRegRendezvous(PVM pVM, PVMCPU pVCpu, void *pvUser)48 {49 PGMMREGISTERSHAREDMODULEREQ pReq = (PGMMREGISTERSHAREDMODULEREQ)pvUser;50 51 return VMMR3CallR0(pVM, VMMR0_DO_PGM_CHECK_SHARED_MODULE, 0, &pReq->Hdr);52 }53 54 /**55 * Shared module registration helper (called on the way out).56 *57 * @param pVM The VM handle.58 * @param pReq Registration request info59 */60 static DECLCALLBACK(void) pgmR3SharedModuleRegisterHelper(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq)61 {62 int rc;63 64 rc = GMMR3RegisterSharedModule(pVM, pReq);65 Assert(rc == VINF_SUCCESS || rc == VINF_PGM_SHARED_MODULE_COLLISION || rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED);66 if (rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED)67 {68 PVMCPU pVCpu = VMMGetCpu(pVM);69 unsigned cFlushedPages = 0;70 71 /** todo count copy-on-write actions in the trap handler so we don't have to check everything all the time! */72 73 /* Count the number of shared pages that were changed (copy-on-write). */74 for (unsigned i = 0; i < pReq->cRegions; i++)75 {76 Assert((pReq->aRegions[i].cbRegion & 0xfff) == 0);77 Assert((pReq->aRegions[i].GCRegionAddr & 0xfff) == 0);78 79 RTGCPTR GCRegion = pReq->aRegions[i].GCRegionAddr;80 uint32_t cbRegion = pReq->aRegions[i].cbRegion & ~0xfff;81 82 while (cbRegion)83 {84 RTGCPHYS GCPhys;85 uint64_t fFlags;86 87 rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);88 if ( rc == VINF_SUCCESS89 && !(fFlags & X86_PTE_RW))90 {91 PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);92 if ( pPage93 && !PGM_PAGE_IS_SHARED(pPage))94 {95 cFlushedPages++;96 }97 }98 99 GCRegion += PAGE_SIZE;100 cbRegion -= PAGE_SIZE;101 }102 }103 104 if (cFlushedPages > 32)105 rc = VINF_SUCCESS; /* force recheck below */106 }107 /* Full (re)check needed? */108 if (rc == VINF_SUCCESS)109 {110 pReq->Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;111 pReq->Hdr.cbReq = RT_OFFSETOF(GMMREGISTERSHAREDMODULEREQ, aRegions[pReq->cRegions]);112 113 /* We must stall other VCPUs as we'd otherwise have to send IPI flush commands for every single change we make. */114 rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, pgmR3SharedModuleRegRendezvous, pReq);115 AssertRC(rc);116 }117 RTMemFree(pReq);118 return;119 }120 #endif121 37 122 38 /** … … 161 77 } 162 78 163 /* Queue the actual registration as we are under the IOM lock right now. Perform this operation on the way out. */ 164 return VMR3ReqCallNoWait(pVM, VMMGetCpuId(pVM), (PFNRT)pgmR3SharedModuleRegisterHelper, 2, pVM, pReq); 79 int rc = GMMR3RegisterSharedModule(pVM, pReq); 80 RTMemFree(pReq); 81 Assert(rc == VINF_SUCCESS || rc == VINF_PGM_SHARED_MODULE_COLLISION || rc == VINF_PGM_SHARED_MODULE_ALREADY_REGISTERED); 82 if (RT_FAILURE(rc)) 83 return rc; 84 return VINF_SUCCESS; 165 85 #else 166 86 return VERR_NOT_IMPLEMENTED; 167 87 #endif 168 88 } 169 170 171 #ifdef VBOX_WITH_PAGE_SHARING172 /**173 * Shared module unregistration helper (called on the way out).174 *175 * @param pVM The VM handle.176 * @param pReq Unregistration request info177 */178 static DECLCALLBACK(void) pgmR3SharedModuleUnregisterHelper(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq)179 {180 int rc;181 182 rc = GMMR3UnregisterSharedModule(pVM, pReq);183 RTMemFree(pReq);184 return;185 }186 #endif187 89 188 90 /** … … 212 114 || RTStrCopy(pReq->szVersion, sizeof(pReq->szVersion), pszVersion) != VINF_SUCCESS) 213 115 { 116 RTMemFree(pReq); 214 117 return VERR_BUFFER_OVERFLOW; 215 118 } 216 /* Queue the actual registration as we are under the IOM lock right now. Perform this operation on the way out. */ 217 return VMR3ReqCallNoWait(pVM, VMMGetCpuId(pVM), (PFNRT)pgmR3SharedModuleUnregisterHelper, 2, pVM, pReq); 119 int rc = GMMR3UnregisterSharedModule(pVM, pReq); 120 RTMemFree(pReq); 121 return rc; 218 122 #else 219 123 return VERR_NOT_IMPLEMENTED; 220 124 #endif 221 125 } 126 127 #ifdef VBOX_WITH_PAGE_SHARING 128 /** 129 * Rendezvous callback that will be called once. 130 * 131 * @returns VBox strict status code. 132 * @param pVM VM handle. 133 * @param pVCpu The VMCPU handle for the calling EMT. 134 * @param pvUser Not used; 135 */ 136 static DECLCALLBACK(VBOXSTRICTRC) pgmR3SharedModuleRegRendezvous(PVM pVM, PVMCPU pVCpu, void *pvUser) 137 { 138 return GMMR3CheckSharedModules(pVM); 139 } 140 141 /** 142 * Shared module unregistration helper (called on the way out). 143 * 144 * @param pVM The VM handle. 145 */ 146 static DECLCALLBACK(void) pgmR3CheckSharedModulesHelper(PVM pVM) 147 { 148 /* We must stall other VCPUs as we'd otherwise have to send IPI flush commands for every single change we make. */ 149 int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, pgmR3SharedModuleRegRendezvous, NULL); 150 AssertRC(rc); 151 } 152 #endif 153 154 /** 155 * Check all registered modules for changes. 156 * 157 * @returns VBox status code. 158 * @param pVM VM handle 159 */ 160 VMMR3DECL(int) PGMR3SharedModuleCheckAll(PVM pVM) 161 { 162 #ifdef VBOX_WITH_PAGE_SHARING 163 /* Queue the actual registration as we are under the IOM lock right now. Perform this operation on the way out. */ 164 return VMR3ReqCallNoWait(pVM, VMMGetCpuId(pVM), (PFNRT)pgmR3CheckSharedModulesHelper, 1, pVM); 165 #else 166 return VERR_NOT_IMPLEMENTED; 167 #endif 168 }
Note:
See TracChangeset
for help on using the changeset viewer.