Changeset 26563 in vbox
- Timestamp:
- Feb 16, 2010 9:50:44 AM (15 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
-
include/VBox/gmm.h (modified) (2 diffs)
-
include/VBox/vmm.h (modified) (1 diff)
-
src/VBox/VMM/VMMR0/GMMR0.cpp (modified) (11 diffs)
-
src/VBox/VMM/VMMR0/VMMR0.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/gmm.h
r26414 r26563 271 271 GMMR0DECL(int) GMMR0AllocateHandyPages(PVM pVM, VMCPUID idCpu, uint32_t cPagesToUpdate, uint32_t cPagesToAlloc, PGMMPAGEDESC paPages); 272 272 GMMR0DECL(int) GMMR0AllocatePages(PVM pVM, VMCPUID idCpu, uint32_t cPages, PGMMPAGEDESC paPages, GMMACCOUNT enmAccount); 273 GMMR0DECL(int) GMMR0AllocateLargePage(PVM pVM, VMCPUID idCpu, uint64_t cbPage, uint32_t *pidPage); 273 274 GMMR0DECL(int) GMMR0FreePages(PVM pVM, VMCPUID idCpu, uint32_t cPages, PGMMFREEPAGEDESC paPages, GMMACCOUNT enmAccount); 275 GMMR0DECL(int) GMMR0FreeLargePage(PVM pVM, VMCPUID idCpu, uint32_t idPage); 274 276 GMMR0DECL(int) GMMR0BalloonedPages(PVM pVM, VMCPUID idCpu, uint32_t cBalloonedPages, uint32_t cPagesToFree, PGMMFREEPAGEDESC paPages, bool fCompleted); 275 277 GMMR0DECL(int) GMMR0DeflatedBalloon(PVM pVM, VMCPUID idCpu, uint32_t cPages); … … 401 403 402 404 GMMR0DECL(int) GMMR0MapUnmapChunkReq(PVM pVM, VMCPUID idCpu, PGMMMAPUNMAPCHUNKREQ pReq); 405 406 /** 407 * Request buffer for GMMR0AllocateLargePageReq / VMMR0_DO_GMM_ALLOC_LARGE_PAGE. 408 * @see GMMR0AllocateLargePage 409 */ 410 typedef struct GMMALLOCLARGEPAGEREQ 411 { 412 /** The header. */ 413 SUPVMMR0REQHDR Hdr; 414 /* Large page size. */ 415 uint32_t cbPage; 416 /** The Page ID. 417 * 418 * @output The ID of the page, NIL_GMM_PAGEID if the allocation failed. 419 */ 420 uint32_t idPage; 421 } GMMALLOCLARGEPAGEREQ; 422 /** Pointer to a GMMR0AllocateLargePageReq / VMMR0_DO_GMM_ALLOC_LARGE_PAGE request buffer. */ 423 typedef GMMALLOCLARGEPAGEREQ *PGMMALLOCLARGEPAGEREQ; 424 425 GMMR0DECL(int) GMMR0AllocateLargePageReq(PVM pVM, VMCPUID idCpu, PGMMALLOCLARGEPAGEREQ pReq); 426 427 428 /** 429 * Request buffer for GMMR0FreeLargePageReq / VMMR0_DO_GMM_FREE_LARGE_PAGE. 430 * @see GMMR0FreeLargePage. 431 */ 432 typedef struct GMMFREELARGEPAGEREQ 433 { 434 /** The header. */ 435 SUPVMMR0REQHDR Hdr; 436 /** The Page ID. */ 437 uint32_t idPage; 438 } GMMFREELARGEPAGEREQ; 439 /** Pointer to a GMMR0FreePagesReq / VMMR0_DO_GMM_FREE_PAGES request buffer. */ 440 typedef GMMFREELARGEPAGEREQ *PGMMFREELARGEPAGEREQ; 441 442 GMMR0DECL(int) GMMR0FreeLargePageReq(PVM pVM, VMCPUID idCpu, PGMMFREELARGEPAGEREQ pReq); 403 443 404 444 -
trunk/include/VBox/vmm.h
r23145 r26563 292 292 /** Call GMMR0AllocatePages(). */ 293 293 VMMR0_DO_GMM_ALLOCATE_PAGES, 294 /** Call GMMR0AllocateLargePage(). */ 295 VMMR0_DO_GMM_ALLOC_LARGE_PAGE, 294 296 /** Call GMMR0FreePages(). */ 295 297 VMMR0_DO_GMM_FREE_PAGES, 298 /** Call GMMR0FreeLargePage(). */ 299 VMMR0_DO_GMM_FREE_LARGE_PAGE, 296 300 /** Call GMMR0BalloonedPages(). */ 297 301 VMMR0_DO_GMM_BALLOONED_PAGES, -
trunk/src/VBox/VMM/VMMR0/GMMR0.cpp
r26542 r26563 1529 1529 * Registers a new chunk of memory. 1530 1530 * 1531 * This is called by both gmmR0AllocateOneChunk and GMMR0SeedChunk. Will take1532 * the mutex, the caller must not own it.1531 * This is called by both gmmR0AllocateOneChunk and GMMR0SeedChunk. The caller 1532 * must own the global lock. 1533 1533 * 1534 1534 * @returns VBox status code. … … 1539 1539 * affinity. 1540 1540 * @param enmChunkType Chunk type (continuous or non-continuous) 1541 */ 1542 static int gmmR0RegisterChunk(PGMM pGMM, PGMMCHUNKFREESET pSet, RTR0MEMOBJ MemObj, uint16_t hGVM, GMMCHUNKTYPE enmChunkType) 1541 * @param ppChunk Chunk address (out) 1542 */ 1543 static int gmmR0RegisterChunk(PGMM pGMM, PGMMCHUNKFREESET pSet, RTR0MEMOBJ MemObj, uint16_t hGVM, GMMCHUNKTYPE enmChunkType, PGMMCHUNK *ppChunk = NULL) 1543 1544 { 1544 1545 Assert(hGVM != NIL_GVM_HANDLE || pGMM->fBoundMemoryMode); … … 1568 1569 * This has to be done behind the mutex of course. 1569 1570 */ 1570 rc = RTSemFastMutexRequest(pGMM->Mtx); 1571 if (RT_SUCCESS(rc)) 1572 { 1573 if (GMM_CHECK_SANITY_UPON_ENTERING(pGMM)) 1571 if (GMM_CHECK_SANITY_UPON_ENTERING(pGMM)) 1572 { 1573 pChunk->Core.Key = gmmR0AllocateChunkId(pGMM); 1574 if ( pChunk->Core.Key != NIL_GMM_CHUNKID 1575 && pChunk->Core.Key <= GMM_CHUNKID_LAST 1576 && RTAvlU32Insert(&pGMM->pChunks, &pChunk->Core)) 1574 1577 { 1575 pChunk->Core.Key = gmmR0AllocateChunkId(pGMM); 1576 if ( pChunk->Core.Key != NIL_GMM_CHUNKID 1577 && pChunk->Core.Key <= GMM_CHUNKID_LAST 1578 && RTAvlU32Insert(&pGMM->pChunks, &pChunk->Core)) 1579 { 1580 pGMM->cChunks++; 1581 gmmR0LinkChunk(pChunk, pSet); 1582 LogFlow(("gmmR0RegisterChunk: pChunk=%p id=%#x cChunks=%d\n", pChunk, pChunk->Core.Key, pGMM->cChunks)); 1583 1584 GMM_CHECK_SANITY_UPON_LEAVING(pGMM); 1585 RTSemFastMutexRelease(pGMM->Mtx); 1586 return VINF_SUCCESS; 1587 } 1588 1589 /* bail out */ 1590 rc = VERR_INTERNAL_ERROR; 1578 pGMM->cChunks++; 1579 gmmR0LinkChunk(pChunk, pSet); 1580 LogFlow(("gmmR0RegisterChunk: pChunk=%p id=%#x cChunks=%d\n", pChunk, pChunk->Core.Key, pGMM->cChunks)); 1581 1582 if (ppChunk) 1583 *ppChunk = pChunk; 1584 1585 GMM_CHECK_SANITY_UPON_LEAVING(pGMM); 1586 RTSemFastMutexRelease(pGMM->Mtx); 1587 return VINF_SUCCESS; 1591 1588 } 1592 else 1593 rc = VERR_INTERNAL_ERROR_5; 1594 1595 RTSemFastMutexRelease(pGMM->Mtx); 1596 } 1589 1590 /* bail out */ 1591 rc = VERR_INTERNAL_ERROR; 1592 } 1593 else 1594 rc = VERR_INTERNAL_ERROR_5; 1595 1597 1596 RTMemFree(pChunk); 1598 1597 } … … 1611 1610 * @param hGVM The affinity of the new chunk. 1612 1611 * @param enmChunkType Chunk type (continuous or non-continuous) 1612 * @param ppChunk Chunk address (out) 1613 1613 * 1614 1614 * @remarks Called without owning the mutex. 1615 1615 */ 1616 static int gmmR0AllocateOneChunk(PGMM pGMM, PGMMCHUNKFREESET pSet, uint16_t hGVM, GMMCHUNKTYPE enmChunkType )1616 static int gmmR0AllocateOneChunk(PGMM pGMM, PGMMCHUNKFREESET pSet, uint16_t hGVM, GMMCHUNKTYPE enmChunkType, PGMMCHUNK *ppChunk = NULL) 1617 1617 { 1618 1618 /* … … 1625 1625 AssertReturn(enmChunkType == GMMCHUNKTYPE_NON_CONTINUOUS || enmChunkType == GMMCHUNKTYPE_CONTINUOUS, VERR_INVALID_PARAMETER); 1626 1626 1627 /* Leave the lock temporarily as the allocation might take long. */ 1628 RTSemFastMutexRelease(pGMM->Mtx); 1627 1629 if (enmChunkType == GMMCHUNKTYPE_NON_CONTINUOUS) 1628 1630 rc = RTR0MemObjAllocPhysNC(&MemObj, GMM_CHUNK_SIZE, NIL_RTHCPHYS); … … 1630 1632 rc = RTR0MemObjAllocPhysEx(&MemObj, GMM_CHUNK_SIZE, NIL_RTHCPHYS, GMM_CHUNK_SIZE); 1631 1633 1634 /* Grab the lock again. */ 1635 int rc2 = RTSemFastMutexRequest(pGMM->Mtx); 1636 AssertRCReturn(rc2, rc2); 1637 1632 1638 if (RT_SUCCESS(rc)) 1633 1639 { 1634 rc = gmmR0RegisterChunk(pGMM, pSet, MemObj, hGVM, enmChunkType );1640 rc = gmmR0RegisterChunk(pGMM, pSet, MemObj, hGVM, enmChunkType, ppChunk); 1635 1641 if (RT_FAILURE(rc)) 1636 1642 RTR0MemObjFree(MemObj, false /* fFreeMappings */); … … 1683 1689 * If we need still more pages, allocate new chunks. 1684 1690 * Note! We will leave the mutex while doing the allocation, 1685 * gmmR0AllocateOneChunk will re-take it temporarily while registering the chunk.1686 1691 */ 1687 1692 while (pSet->cFreePages < cPages) 1688 1693 { 1689 RTSemFastMutexRelease(pGMM->Mtx);1690 1694 int rc = gmmR0AllocateOneChunk(pGMM, pSet, pGVM->hSelf, GMMCHUNKTYPE_NON_CONTINUOUS); 1691 int rc2 = RTSemFastMutexRequest(pGMM->Mtx);1692 AssertRCReturn(rc2, rc2);1693 1695 if (RT_FAILURE(rc)) 1694 1696 return rc; … … 1705 1707 * 1706 1708 * Note! We will leave the mutex while doing the allocation, 1707 * gmmR0AllocateOneChunk will re-take it temporarily while registering the chunk.1708 1709 */ 1709 1710 uint16_t const hGVM = pGVM->hSelf; … … 1724 1725 1725 1726 /* Allocate more. */ 1726 RTSemFastMutexRelease(pGMM->Mtx);1727 1727 int rc = gmmR0AllocateOneChunk(pGMM, pSet, hGVM, GMMCHUNKTYPE_NON_CONTINUOUS); 1728 int rc2 = RTSemFastMutexRequest(pGMM->Mtx);1729 AssertRCReturn(rc2, rc2);1730 1728 if (RT_FAILURE(rc)) 1731 1729 return rc; … … 2277 2275 } 2278 2276 2277 /** 2278 * Allocate a large page to represent guest RAM 2279 * 2280 * The allocated pages are not cleared and will contains random garbage. 2281 * 2282 * @returns VBox status code: 2283 * @retval VINF_SUCCESS on success. 2284 * @retval VERR_NOT_OWNER if the caller is not an EMT. 2285 * @retval VERR_GMM_SEED_ME if seeding via GMMR0SeedChunk is necessary. 2286 * @retval VERR_GMM_HIT_GLOBAL_LIMIT if we've exhausted the available pages. 2287 * @retval VERR_GMM_HIT_VM_ACCOUNT_LIMIT if we've hit the VM account limit, 2288 * that is we're trying to allocate more than we've reserved. 2289 * @returns see GMMR0AllocatePages. 2290 * @param pVM Pointer to the shared VM structure. 2291 * @param idCpu VCPU id 2292 * @param cbPage Large page size 2293 * @param pidPage Id of the page (out) 2294 */ 2295 GMMR0DECL(int) GMMR0AllocateLargePage(PVM pVM, VMCPUID idCpu, uint32_t cbPage, uint32_t *pidPage) 2296 { 2297 LogFlow(("GMMR0AllocateLargePage: pVM=%p cbPage=%x\n", pVM, cbPage)); 2298 2299 AssertReturn(cbPage == GMM_CHUNK_SIZE, VERR_INVALID_PARAMETER); 2300 2301 /* 2302 * Validate, get basics and take the semaphore. 2303 */ 2304 PGMM pGMM; 2305 GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR); 2306 PGVM pGVM; 2307 int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM); 2308 if (RT_FAILURE(rc)) 2309 return rc; 2310 2311 /* Not supported in legacy mode where we allocate the memory in ring 3 and lock it in ring 0. */ 2312 if (pGMM->fLegacyAllocationMode) 2313 return VERR_NOT_SUPPORTED; 2314 2315 *pidPage = NIL_GMM_PAGEID; 2316 2317 rc = RTSemFastMutexRequest(pGMM->Mtx); 2318 AssertRCReturn(rc, rc); 2319 if (GMM_CHECK_SANITY_UPON_ENTERING(pGMM)) 2320 { 2321 const unsigned cPages = (GMM_CHUNK_SIZE >> PAGE_SHIFT); 2322 PGMMCHUNK pChunk; 2323 GMMPAGEDESC PageDesc; 2324 2325 if (RT_UNLIKELY(pGVM->gmm.s.Allocated.cBasePages + cPages > pGVM->gmm.s.Reserved.cBasePages)) 2326 { 2327 Log(("GMMR0AllocateLargePage: Reserved=%#llx Allocated+Requested=%#llx+%#x!\n", 2328 pGVM->gmm.s.Reserved.cBasePages, pGVM->gmm.s.Allocated.cBasePages, cPages)); 2329 RTSemFastMutexRelease(pGMM->Mtx); 2330 return VERR_GMM_HIT_VM_ACCOUNT_LIMIT; 2331 } 2332 2333 /* Allocate a new continous chunk. */ 2334 rc = gmmR0AllocateOneChunk(pGMM, &pGMM->Private, pGVM->hSelf, GMMCHUNKTYPE_CONTINUOUS, &pChunk); 2335 if (RT_FAILURE(rc)) 2336 { 2337 RTSemFastMutexRelease(pGMM->Mtx); 2338 return rc; 2339 } 2340 2341 /* Unlink the new chunk from the free list. */ 2342 gmmR0UnlinkChunk(pChunk); 2343 2344 /* Allocate all pages. */ 2345 gmmR0AllocatePage(pGMM, pGVM->hSelf, pChunk, &PageDesc); 2346 /* Return the first page as we'll use the whole chunk as one big page. */ 2347 *pidPage = PageDesc.idPage; 2348 2349 for (unsigned i = 1; i < cPages; i++) 2350 gmmR0AllocatePage(pGMM, pGVM->hSelf, pChunk, &PageDesc); 2351 2352 /* Update accounting. */ 2353 pGVM->gmm.s.Allocated.cBasePages += cPages; 2354 pGVM->gmm.s.cPrivatePages += cPages; 2355 pGMM->cAllocatedPages += cPages; 2356 2357 gmmR0LinkChunk(pChunk, &pGMM->Private); 2358 } 2359 else 2360 rc = VERR_INTERNAL_ERROR_5; 2361 2362 RTSemFastMutexRelease(pGMM->Mtx); 2363 LogFlow(("GMMR0AllocatePages: returns %Rrc\n", rc)); 2364 return rc; 2365 } 2366 2367 2368 /** 2369 * VMMR0 request wrapper for GMMR0AllocateLargePage. 2370 * 2371 * @returns see GMMR0AllocateLargePage. 2372 * @param pVM Pointer to the shared VM structure. 2373 * @param idCpu VCPU id 2374 * @param pReq The request packet. 2375 */ 2376 GMMR0DECL(int) GMMR0AllocateLargePageReq(PVM pVM, VMCPUID idCpu, PGMMALLOCLARGEPAGEREQ pReq) 2377 { 2378 /* 2379 * Validate input and pass it on. 2380 */ 2381 AssertPtrReturn(pVM, VERR_INVALID_POINTER); 2382 AssertPtrReturn(pReq, VERR_INVALID_POINTER); 2383 AssertMsgReturn(pReq->Hdr.cbReq == sizeof(GMMALLOCATEPAGESREQ), 2384 ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(GMMALLOCATEPAGESREQ)), 2385 VERR_INVALID_PARAMETER); 2386 2387 return GMMR0AllocateLargePage(pVM, idCpu, pReq->cbPage, &pReq->idPage); 2388 } 2389 2390 2391 /** 2392 * Free a large page 2393 * 2394 * @returns VBox status code: 2395 * @param pVM Pointer to the shared VM structure. 2396 * @param idCpu VCPU id 2397 * @param idPage Large page id 2398 */ 2399 GMMR0DECL(int) GMMR0FreeLargePage(PVM pVM, VMCPUID idCpu, uint32_t idPage) 2400 { 2401 LogFlow(("GMMR0FreeLargePage: pVM=%p idPage=%x\n", pVM, idPage)); 2402 2403 /* 2404 * Validate, get basics and take the semaphore. 2405 */ 2406 PGMM pGMM; 2407 GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR); 2408 PGVM pGVM; 2409 int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM); 2410 if (RT_FAILURE(rc)) 2411 return rc; 2412 2413 /* Not supported in legacy mode where we allocate the memory in ring 3 and lock it in ring 0. */ 2414 if (pGMM->fLegacyAllocationMode) 2415 return VERR_NOT_SUPPORTED; 2416 2417 rc = RTSemFastMutexRequest(pGMM->Mtx); 2418 AssertRC(rc); 2419 if (GMM_CHECK_SANITY_UPON_ENTERING(pGMM)) 2420 { 2421 const unsigned cPages = (GMM_CHUNK_SIZE >> PAGE_SHIFT); 2422 2423 if (RT_UNLIKELY(pGVM->gmm.s.Allocated.cBasePages < cPages)) 2424 { 2425 Log(("gmmR0FreePages: allocated=%#llx cPages=%#x!\n", pGVM->gmm.s.Allocated.cBasePages, cPages)); 2426 RTSemFastMutexRelease(pGMM->Mtx); 2427 return VERR_GMM_ATTEMPT_TO_FREE_TOO_MUCH; 2428 } 2429 2430 PGMMPAGE pPage = gmmR0GetPage(pGMM, idPage); 2431 if ( RT_LIKELY(pPage) 2432 && RT_LIKELY(GMM_PAGE_IS_PRIVATE(pPage))) 2433 { 2434 PGMMCHUNK pChunk = gmmR0GetChunk(pGMM, idPage >> GMM_CHUNKID_SHIFT); 2435 Assert(pChunk); 2436 Assert(pChunk->cFree < GMM_CHUNK_NUM_PAGES); 2437 Assert(pChunk->cPrivate > 0); 2438 2439 /* Release the memory immediately. */ 2440 gmmR0FreeChunk(pGMM, NULL, pChunk); 2441 2442 /* Update accounting. */ 2443 pGVM->gmm.s.Allocated.cBasePages -= cPages; 2444 pGVM->gmm.s.cPrivatePages -= cPages; 2445 pGMM->cAllocatedPages -= cPages; 2446 } 2447 else 2448 rc = VERR_GMM_PAGE_NOT_FOUND; 2449 } 2450 else 2451 rc = VERR_INTERNAL_ERROR_5; 2452 2453 RTSemFastMutexRelease(pGMM->Mtx); 2454 LogFlow(("GMMR0FreeLargePage: returns %Rrc\n", rc)); 2455 return rc; 2456 } 2457 2458 2459 /** 2460 * VMMR0 request wrapper for GMMR0FreeLargePage. 2461 * 2462 * @returns see GMMR0FreeLargePage. 2463 * @param pVM Pointer to the shared VM structure. 2464 * @param idCpu VCPU id 2465 * @param pReq The request packet. 2466 */ 2467 GMMR0DECL(int) GMMR0FreeLargePageReq(PVM pVM, VMCPUID idCpu, PGMMFREELARGEPAGEREQ pReq) 2468 { 2469 /* 2470 * Validate input and pass it on. 2471 */ 2472 AssertPtrReturn(pVM, VERR_INVALID_POINTER); 2473 AssertPtrReturn(pReq, VERR_INVALID_POINTER); 2474 AssertMsgReturn(pReq->Hdr.cbReq == sizeof(GMMFREEPAGESREQ), 2475 ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(GMMFREEPAGESREQ)), 2476 VERR_INVALID_PARAMETER); 2477 2478 return GMMR0FreeLargePage(pVM, idCpu, pReq->idPage); 2479 } 2279 2480 2280 2481 /** … … 3133 3334 if (RT_SUCCESS(rc)) 3134 3335 { 3336 /* Grab the lock. */ 3337 rc = RTSemFastMutexRequest(pGMM->Mtx); 3338 AssertRCReturn(rc, rc); 3339 3135 3340 /* 3136 3341 * Add a new chunk with our hGVM. 3137 3342 */ 3138 3343 rc = gmmR0RegisterChunk(pGMM, &pGMM->Private, MemObj, pGVM->hSelf, GMMCHUNKTYPE_NON_CONTINUOUS); 3344 RTSemFastMutexRelease(pGMM->Mtx); 3345 3139 3346 if (RT_FAILURE(rc)) 3140 3347 RTR0MemObjFree(MemObj, false /* fFreeMappings */); -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r26066 r26563 895 895 return GMMR0AllocatePagesReq(pVM, idCpu, (PGMMALLOCATEPAGESREQ)pReqHdr); 896 896 897 case VMMR0_DO_GMM_ALLOC_LARGE_PAGE: 898 if (u64Arg) 899 return VERR_INVALID_PARAMETER; 900 return GMMR0AllocateLargePageReq(pVM, idCpu, (PGMMALLOCLARGEPAGEREQ)pReqHdr); 901 897 902 case VMMR0_DO_GMM_FREE_PAGES: 898 903 if (u64Arg) 899 904 return VERR_INVALID_PARAMETER; 900 905 return GMMR0FreePagesReq(pVM, idCpu, (PGMMFREEPAGESREQ)pReqHdr); 906 907 case VMMR0_DO_GMM_FREE_LARGE_PAGE: 908 if (u64Arg) 909 return VERR_INVALID_PARAMETER; 910 return GMMR0FreeLargePageReq(pVM, idCpu, (PGMMFREELARGEPAGEREQ)pReqHdr); 901 911 902 912 case VMMR0_DO_GMM_BALLOONED_PAGES:
Note:
See TracChangeset
for help on using the changeset viewer.

