Changeset 92390 in vbox
- Timestamp:
- Nov 12, 2021 9:24:33 AM (3 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
-
VMMR0/PGMR0.cpp (modified) (5 diffs)
-
VMMR3/PGMPhys.cpp (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/PGMR0.cpp
r92389 r92390 133 133 * @param pGVM The global (ring-0) VM structure. 134 134 * @param idCpu The ID of the calling EMT. 135 * @param fRing3 Set if the caller is ring-3. Determins whether to 136 * return VINF_EM_NO_MEMORY or not. 135 137 * 136 138 * @thread EMT(idCpu) … … 139 141 * must clear the new pages. 140 142 */ 141 VMMR0_INT_DECL(int) PGMR0PhysAllocateHandyPages(PGVM pGVM, VMCPUID idCpu)143 int pgmR0PhysAllocateHandyPages(PGVM pGVM, VMCPUID idCpu, bool fRing3) 142 144 { 143 145 /* … … 145 147 */ 146 148 AssertReturn(idCpu < pGVM->cCpus, VERR_INVALID_CPU_ID); /* caller already checked this, but just to be sure. */ 147 Assert Return(pGVM->aCpus[idCpu].hEMT == RTThreadNativeSelf(), VERR_NOT_OWNER);149 Assert(pGVM->aCpus[idCpu].hEMT == RTThreadNativeSelf()); 148 150 PGM_LOCK_ASSERT_OWNER_EX(pGVM, &pGVM->aCpus[idCpu]); 149 151 … … 159 161 * Try allocate a full set of handy pages. 160 162 */ 161 uint32_t iFirst = pGVM->pgm.s.cHandyPages; 162 AssertReturn(iFirst <= RT_ELEMENTS(pGVM->pgm.s.aHandyPages), VERR_PGM_HANDY_PAGE_IPE); 163 uint32_t cPages = RT_ELEMENTS(pGVM->pgm.s.aHandyPages) - iFirst; 163 uint32_t const iFirst = pGVM->pgm.s.cHandyPages; 164 AssertMsgReturn(iFirst <= RT_ELEMENTS(pGVM->pgm.s.aHandyPages), ("%#x\n", iFirst), VERR_PGM_HANDY_PAGE_IPE); 165 166 uint32_t const cPages = RT_ELEMENTS(pGVM->pgm.s.aHandyPages) - iFirst; 164 167 if (!cPages) 165 168 return VINF_SUCCESS; 169 166 170 int rc = GMMR0AllocateHandyPages(pGVM, idCpu, cPages, cPages, &pGVM->pgm.s.aHandyPages[iFirst]); 167 171 if (RT_SUCCESS(rc)) 168 172 { 173 uint32_t const cHandyPages = RT_ELEMENTS(pGVM->pgm.s.aHandyPages); /** @todo allow allocating less... */ 174 pGVM->pgm.s.cHandyPages = cHandyPages; 175 VM_FF_CLEAR(pGVM, VM_FF_PGM_NEED_HANDY_PAGES); 176 VM_FF_CLEAR(pGVM, VM_FF_PGM_NO_MEMORY); 177 169 178 #ifdef VBOX_STRICT 170 for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->pgm.s.aHandyPages); i++)179 for (uint32_t i = 0; i < cHandyPages; i++) 171 180 { 172 181 Assert(pGVM->pgm.s.aHandyPages[i].idPage != NIL_GMM_PAGEID); … … 178 187 #endif 179 188 180 pGVM->pgm.s.cHandyPages = RT_ELEMENTS(pGVM->pgm.s.aHandyPages); 189 /* 190 * Clear the pages. 191 */ 192 for (uint32_t iPage = iFirst; iPage < cHandyPages; iPage++) 193 { 194 PGMMPAGEDESC pPage = &pGVM->pgm.s.aHandyPages[iPage]; 195 if (!pPage->fZeroed) 196 { 197 void *pv = NULL; 198 #ifdef VBOX_WITH_LINEAR_HOST_PHYS_MEM 199 rc = SUPR0HCPhysToVirt(pPage->HCPhysGCPhys, &pv); 200 #else 201 rc = GMMR0PageIdToVirt(pGVM, pPage->idPage, &pv); 202 #endif 203 AssertMsgRCReturn(rc, ("idPage=%#x HCPhys=%RHp rc=%Rrc\n", pPage->idPage, pPage->HCPhysGCPhys, rc), rc); 204 205 ASMMemZeroPage(pv); 206 pPage->fZeroed = true; 207 } 208 #ifdef VBOX_STRICT 209 else 210 { 211 void *pv = NULL; 212 # ifdef VBOX_WITH_LINEAR_HOST_PHYS_MEM 213 rc = SUPR0HCPhysToVirt(pPage->HCPhysGCPhys, &pv); 214 # else 215 rc = GMMR0PageIdToVirt(pGVM, pPage->idPage, &pv); 216 # endif 217 AssertMsgRCReturn(rc, ("idPage=%#x HCPhys=%RHp rc=%Rrc\n", pPage->idPage, pPage->HCPhysGCPhys, rc), rc); 218 AssertReturn(ASMMemIsZeroPage(pv), VERR_PGM_HANDY_PAGE_IPE); 219 } 220 #endif 221 Log3(("PGMR0PhysAllocateHandyPages: idPage=%#x HCPhys=%RGp\n", pPage->idPage, pPage->HCPhysGCPhys)); 222 } 181 223 } 182 224 else 183 225 { 184 LogRel(("PGMR0PhysAllocateHandyPages: rc=%Rrc iFirst=%d cPages=%d\n", rc, iFirst, cPages)); 226 /* 227 * We should never get here unless there is a genuine shortage of 228 * memory (or some internal error). Flag the error so the VM can be 229 * suspended ASAP and the user informed. If we're totally out of 230 * handy pages we will return failure. 231 */ 232 /* Report the failure. */ 233 LogRel(("PGM: Failed to procure handy pages; rc=%Rrc cHandyPages=%#x\n" 234 " cAllPages=%#x cPrivatePages=%#x cSharedPages=%#x cZeroPages=%#x\n", 235 rc, pGVM->pgm.s.cHandyPages, 236 pGVM->pgm.s.cAllPages, pGVM->pgm.s.cPrivatePages, pGVM->pgm.s.cSharedPages, pGVM->pgm.s.cZeroPages)); 237 238 GMMMEMSTATSREQ Stats = { { SUPVMMR0REQHDR_MAGIC, sizeof(Stats) }, 0, 0, 0, 0, 0 }; 239 if (RT_SUCCESS(GMMR0QueryMemoryStatsReq(pGVM, idCpu, &Stats))) 240 LogRel(("GMM: Statistics:\n" 241 " Allocated pages: %RX64\n" 242 " Free pages: %RX64\n" 243 " Shared pages: %RX64\n" 244 " Maximum pages: %RX64\n" 245 " Ballooned pages: %RX64\n", 246 Stats.cAllocPages, Stats.cFreePages, Stats.cSharedPages, Stats.cMaxPages, Stats.cBalloonedPages)); 247 248 if ( rc != VERR_NO_MEMORY 249 && rc != VERR_NO_PHYS_MEMORY 250 && rc != VERR_LOCK_FAILED) 251 for (uint32_t iPage = 0; iPage < RT_ELEMENTS(pGVM->pgm.s.aHandyPages); iPage++) 252 LogRel(("PGM: aHandyPages[#%#04x] = {.HCPhysGCPhys=%RHp, .idPage=%#08x, .idSharedPage=%#08x}\n", 253 iPage, pGVM->pgm.s.aHandyPages[iPage].HCPhysGCPhys, pGVM->pgm.s.aHandyPages[iPage].idPage, 254 pGVM->pgm.s.aHandyPages[iPage].idSharedPage)); 255 256 /* Set the FFs and adjust rc. */ 257 VM_FF_SET(pGVM, VM_FF_PGM_NEED_HANDY_PAGES); 185 258 VM_FF_SET(pGVM, VM_FF_PGM_NO_MEMORY); 259 if (!fRing3) 260 if ( rc == VERR_NO_MEMORY 261 || rc == VERR_NO_PHYS_MEMORY 262 || rc == VERR_LOCK_FAILED 263 || rc == VERR_MAP_FAILED) 264 rc = VINF_EM_NO_MEMORY; 186 265 } 187 266 188 267 LogFlow(("PGMR0PhysAllocateHandyPages: cPages=%d rc=%Rrc\n", cPages, rc)); 268 return rc; 269 } 270 271 272 /** 273 * Worker function for PGMR3PhysAllocateHandyPages / VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES. 274 * 275 * @returns The following VBox status codes. 276 * @retval VINF_SUCCESS on success. FF cleared. 277 * @retval VINF_EM_NO_MEMORY if we're out of memory. The FF is set in this case. 278 * 279 * @param pGVM The global (ring-0) VM structure. 280 * @param idCpu The ID of the calling EMT. 281 * 282 * @thread EMT(idCpu) 283 * 284 * @remarks Must be called from within the PGM critical section. The caller 285 * must clear the new pages. 286 */ 287 VMMR0_INT_DECL(int) PGMR0PhysAllocateHandyPages(PGVM pGVM, VMCPUID idCpu) 288 { 289 /* 290 * Validate inputs. 291 */ 292 AssertReturn(idCpu < pGVM->cCpus, VERR_INVALID_CPU_ID); /* caller already checked this, but just to be sure. */ 293 AssertReturn(pGVM->aCpus[idCpu].hEMT == RTThreadNativeSelf(), VERR_NOT_OWNER); 294 295 /* 296 * Enter the PGM lock and call the worker. 297 */ 298 int rc = PGM_LOCK(pGVM); 299 if (RT_SUCCESS(rc)) 300 { 301 rc = pgmR0PhysAllocateHandyPages(pGVM, idCpu, true /*fRing3*/); 302 PGM_UNLOCK(pGVM); 303 } 189 304 return rc; 190 305 } -
trunk/src/VBox/VMM/VMMR3/PGMPhys.cpp
r92368 r92390 5843 5843 AssertMsgReturn(iClear <= RT_ELEMENTS(pVM->pgm.s.aHandyPages), ("%d", iClear), VERR_PGM_HANDY_PAGE_IPE); 5844 5844 Log(("PGMR3PhysAllocateHandyPages: %d -> %d\n", iClear, RT_ELEMENTS(pVM->pgm.s.aHandyPages))); 5845 int rcAlloc = VINF_SUCCESS;5846 int rcSeed = VINF_SUCCESS;5847 5845 int rc = VMMR3CallR0(pVM, VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES, 0, NULL); 5848 5846 /** @todo we should split this up into an allocate and flush operation. sometimes you want to flush and not allocate more (which will trigger the vm account limit error) */ … … 5858 5856 AssertMsg(rc == VINF_SUCCESS, ("%Rrc\n", rc)); 5859 5857 Assert(pVM->pgm.s.cHandyPages > 0); 5860 VM_FF_CLEAR(pVM, VM_FF_PGM_NEED_HANDY_PAGES);5861 VM_FF_CLEAR(pVM, VM_FF_PGM_NO_MEMORY);5862 5863 5858 #ifdef VBOX_STRICT 5864 5859 uint32_t i; … … 5881 5876 } 5882 5877 #endif 5883 /*5884 * Clear the pages.5885 */5886 while (iClear < pVM->pgm.s.cHandyPages)5887 {5888 PGMMPAGEDESC pPage = &pVM->pgm.s.aHandyPages[iClear];5889 if (!pPage->fZeroed)5890 {5891 void *pv;5892 rc = pgmPhysPageMapByPageID(pVM, pPage->idPage, pPage->HCPhysGCPhys, &pv);5893 AssertLogRelMsgBreak(RT_SUCCESS(rc),5894 ("%u/%u: idPage=%#x HCPhysGCPhys=%RHp rc=%Rrc\n",5895 iClear, pVM->pgm.s.cHandyPages, pPage->idPage, pPage->HCPhysGCPhys, rc));5896 ASMMemZeroPage(pv);5897 pPage->fZeroed = true;5898 }5899 #ifdef VBOX_STRICT5900 else5901 {5902 void *pv;5903 rc = pgmPhysPageMapByPageID(pVM, pPage->idPage, pPage->HCPhysGCPhys, &pv);5904 AssertLogRelMsgBreak(RT_SUCCESS(rc),5905 ("%u/%u: idPage=%#x HCPhysGCPhys=%RHp rc=%Rrc\n",5906 iClear, pVM->pgm.s.cHandyPages, pPage->idPage, pPage->HCPhysGCPhys, rc));5907 Assert(ASMMemIsZeroPage(pv));5908 }5909 #endif5910 iClear++;5911 Log3(("PGMR3PhysAllocateHandyPages: idPage=%#x HCPhys=%RGp\n", pPage->idPage, pPage->HCPhysGCPhys));5912 }5913 5878 } 5914 5879 else 5915 5880 { 5916 uint64_t cAllocPages, cMaxPages, cBalloonPages;5917 5918 5881 /* 5919 5882 * We should never get here unless there is a genuine shortage of … … 5923 5886 */ 5924 5887 /* Report the failure. */ 5925 LogRel(("PGM: Failed to procure handy pages; rc=%Rrc rcAlloc=%Rrc rcSeed=%RrccHandyPages=%#x\n"5888 LogRel(("PGM: Failed to procure handy pages; rc=%Rrc cHandyPages=%#x\n" 5926 5889 " cAllPages=%#x cPrivatePages=%#x cSharedPages=%#x cZeroPages=%#x\n", 5927 rc, rcAlloc, rcSeed, 5928 pVM->pgm.s.cHandyPages, 5929 pVM->pgm.s.cAllPages, 5930 pVM->pgm.s.cPrivatePages, 5931 pVM->pgm.s.cSharedPages, 5932 pVM->pgm.s.cZeroPages)); 5933 5934 if (GMMR3QueryMemoryStats(pVM, &cAllocPages, &cMaxPages, &cBalloonPages) == VINF_SUCCESS) 5935 { 5936 LogRel(("GMM: Statistics:\n" 5937 " Allocated pages: %RX64\n" 5938 " Maximum pages: %RX64\n" 5939 " Ballooned pages: %RX64\n", cAllocPages, cMaxPages, cBalloonPages)); 5940 } 5890 rc, pVM->pgm.s.cHandyPages, 5891 pVM->pgm.s.cAllPages, pVM->pgm.s.cPrivatePages, pVM->pgm.s.cSharedPages, pVM->pgm.s.cZeroPages)); 5941 5892 5942 5893 if ( rc != VERR_NO_MEMORY 5943 5894 && rc != VERR_NO_PHYS_MEMORY 5944 5895 && rc != VERR_LOCK_FAILED) 5945 {5946 5896 for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++) 5947 5897 { … … 5964 5914 } 5965 5915 } 5966 }5967 5916 5968 5917 if (rc == VERR_NO_MEMORY)
Note:
See TracChangeset
for help on using the changeset viewer.

