Changeset 37193 in vbox for trunk/src/VBox
- Timestamp:
- May 24, 2011 1:09:05 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/GMMR0.cpp
r37192 r37193 370 370 /** Pointer to a GMM allocation chunk mapping. */ 371 371 typedef struct GMMCHUNKMAP *PGMMCHUNKMAP; 372 373 typedef enum GMMCHUNKTYPE374 {375 GMMCHUNKTYPE_INVALID = 0,376 GMMCHUNKTYPE_NON_CONTINUOUS = 1, /* 4 kb pages */377 GMMCHUNKTYPE_CONTINUOUS = 2, /* one 2 MB continuous physical range. */378 GMMCHUNKTYPE_32BIT_HACK = 0x7fffffff379 } GMMCHUNKTYPE;380 372 381 373 … … 429 421 /** The number of shared pages. (Giant mtx.) */ 430 422 uint16_t cShared; 431 /** Chunk type. (Giant mtx.) */432 GMMCHUNKTYPE enmType;433 423 /** The pages. (Giant mtx.) */ 434 424 GMMPAGE aPages[GMM_CHUNK_SIZE >> PAGE_SHIFT]; 435 425 } GMMCHUNK; 426 427 /** Indicates that the NUMA properies of the memory is unknown. */ 428 #define GMM_CHUNK_NUMA_ID_UNKNOWN UINT16_C(0xfffe) 429 430 /** @name GMM_CHUNK_FLAGS_XXX - chunk flags. 431 * @{ */ 432 /** Indicates that the chunk is a large page (2MB). */ 433 #define GMM_CHUNK_FLAGS_LARGE_PAGE UINT16_C(0x0001) 434 /** @} */ 436 435 437 436 … … 474 473 #define GMM_CHUNK_FREE_SET_LISTS (GMM_CHUNK_NUM_PAGES >> GMM_CHUNK_FREE_SET_SHIFT) 475 474 476 /** Indicates that the NUMA properies of the memory is unknown. */477 #define GMM_CHUNK_NUMA_ID_UNKNOWN UINT16_C(0xfffe)478 475 479 476 /** … … 766 763 /* Don't reuse possibly partial chunks because of the virtual 767 764 address space limitation. */ 768 pGMM->fBoundMemoryMode = true;765 pGMM->fBoundMemoryMode = true; 769 766 # else 770 pGMM->fBoundMemoryMode = false;767 pGMM->fBoundMemoryMode = false; 771 768 # endif 772 769 # else 773 770 pGMM->fLegacyAllocationMode = true; 774 pGMM->fBoundMemoryMode = true;771 pGMM->fBoundMemoryMode = true; 775 772 # endif 776 773 #endif … … 1802 1799 */ 1803 1800 int32_t idChunk = ++pGMM->idChunkPrev; 1804 #if 0 /* test the fallback first*/1801 #if 0 /** @todo enable this code */ 1805 1802 if ( idChunk <= GMM_CHUNKID_LAST 1806 1803 && idChunk > NIL_GMM_CHUNKID … … 1838 1835 * Registers a new chunk of memory. 1839 1836 * 1840 * This is called by both gmmR0AllocateOneChunk and GMMR0SeedChunk. The caller1841 * must own the global lock.1842 * 1843 * @returns VBox status code.1837 * This is called by both gmmR0AllocateOneChunk and GMMR0SeedChunk. 1838 * 1839 * @returns VBox status code. On success, the giant GMM lock will be held, the 1840 * caller must release it (ugly). 1844 1841 * @param pGMM Pointer to the GMM instance. 1845 1842 * @param pSet Pointer to the set. … … 1847 1844 * @param hGVM The affinity of the chunk. NIL_GVM_HANDLE for no 1848 1845 * affinity. 1849 * @param enmChunkType Chunk type (continuous or non-continuous) 1850 * @param ppChunk Chunk address (out) 1851 */ 1852 static int gmmR0RegisterChunk(PGMM pGMM, PGMMCHUNKFREESET pSet, RTR0MEMOBJ MemObj, uint16_t hGVM, GMMCHUNKTYPE enmChunkType, PGMMCHUNK *ppChunk = NULL) 1853 { 1846 * @param fChunkFlags The chunk flags, GMM_CHUNK_FLAGS_XXX. 1847 * @param ppChunk Chunk address (out). Optional. 1848 * 1849 * @remarks The caller must not own the giant GMM mutex. 1850 * The giant GMM mutex will be acquired and returned acquired in 1851 * the success path. On failure, no locks will be held. 1852 */ 1853 static int gmmR0RegisterChunk(PGMM pGMM, PGMMCHUNKFREESET pSet, RTR0MEMOBJ MemObj, uint16_t hGVM, uint16_t fChunkFlags, 1854 PGMMCHUNK *ppChunk) 1855 { 1856 Assert(pGMM->hMtxOwner != RTThreadNativeSelf()); 1854 1857 Assert(hGVM != NIL_GVM_HANDLE || pGMM->fBoundMemoryMode); 1858 Assert(fChunkFlags == 0 || fChunkFlags == GMM_CHUNK_FLAGS_LARGE_PAGE); 1855 1859 1856 1860 int rc; … … 1866 1870 /*pChunk->iFreeHead = 0;*/ 1867 1871 pChunk->idNumaNode = GMM_CHUNK_NUMA_ID_UNKNOWN; 1868 pChunk-> enmType = enmChunkType;1872 pChunk->fFlags = fChunkFlags; 1869 1873 for (unsigned iPage = 0; iPage < RT_ELEMENTS(pChunk->aPages) - 1; iPage++) 1870 1874 { … … 1879 1883 * This has to be done behind the mutex of course. 1880 1884 */ 1881 if (GMM_CHECK_SANITY_UPON_ENTERING(pGMM)) 1882 { 1883 pChunk->Core.Key = gmmR0AllocateChunkId(pGMM); 1884 if ( pChunk->Core.Key != NIL_GMM_CHUNKID 1885 && pChunk->Core.Key <= GMM_CHUNKID_LAST 1886 && RTAvlU32Insert(&pGMM->pChunks, &pChunk->Core)) 1885 rc = gmmR0MutexAcquire(pGMM); 1886 if (RT_SUCCESS(rc)) 1887 { 1888 if (GMM_CHECK_SANITY_UPON_ENTERING(pGMM)) 1887 1889 { 1888 pGMM->cChunks++; 1889 RTListAppend(&pGMM->ChunkList, &pChunk->ListNode); 1890 gmmR0LinkChunk(pChunk, pSet); 1891 LogFlow(("gmmR0RegisterChunk: pChunk=%p id=%#x cChunks=%d\n", pChunk, pChunk->Core.Key, pGMM->cChunks)); 1892 1893 if (ppChunk) 1894 *ppChunk = pChunk; 1895 1896 GMM_CHECK_SANITY_UPON_LEAVING(pGMM); 1897 return VINF_SUCCESS; 1890 pChunk->Core.Key = gmmR0AllocateChunkId(pGMM); 1891 if ( pChunk->Core.Key != NIL_GMM_CHUNKID 1892 && pChunk->Core.Key <= GMM_CHUNKID_LAST 1893 && RTAvlU32Insert(&pGMM->pChunks, &pChunk->Core)) 1894 { 1895 pGMM->cChunks++; 1896 RTListAppend(&pGMM->ChunkList, &pChunk->ListNode); 1897 gmmR0LinkChunk(pChunk, pSet); 1898 LogFlow(("gmmR0RegisterChunk: pChunk=%p id=%#x cChunks=%d\n", pChunk, pChunk->Core.Key, pGMM->cChunks)); 1899 1900 if (ppChunk) 1901 *ppChunk = pChunk; 1902 GMM_CHECK_SANITY_UPON_LEAVING(pGMM); 1903 return VINF_SUCCESS; 1904 } 1905 1906 /* bail out */ 1907 rc = VERR_INTERNAL_ERROR; 1898 1908 } 1899 1900 /* bail out */ 1901 rc = VERR_INTERNAL_ERROR; 1902 } 1903 else 1904 rc = VERR_INTERNAL_ERROR_5; 1909 else 1910 rc = VERR_INTERNAL_ERROR_5; 1911 gmmR0MutexRelease(pGMM); 1912 } 1905 1913 1906 1914 RTMemFree(pChunk); … … 1919 1927 * @param pSet Pointer to the set. 1920 1928 * @param hGVM The affinity of the new chunk. 1921 * @param enmChunkType Chunk type (continuous or non-continuous) 1922 * @param ppChunk Chunk address (out) 1923 * 1924 * @remarks Called without owning the mutex. 1925 */ 1926 static int gmmR0AllocateOneChunk(PGMM pGMM, PGMMCHUNKFREESET pSet, uint16_t hGVM, GMMCHUNKTYPE enmChunkType, PGMMCHUNK *ppChunk = NULL) 1929 * 1930 * @remarks The giant mutex will be temporarily abandond during the allocation. 1931 */ 1932 static int gmmR0AllocateOneChunk(PGMM pGMM, PGMMCHUNKFREESET pSet, uint16_t hGVM) 1927 1933 { 1928 1934 /* 1929 1935 * Allocate the memory. 1930 */ 1931 RTR0MEMOBJ MemObj; 1932 int rc; 1933 1934 AssertCompile(GMM_CHUNK_SIZE == _2M); 1935 AssertReturn(enmChunkType == GMMCHUNKTYPE_NON_CONTINUOUS || enmChunkType == GMMCHUNKTYPE_CONTINUOUS, VERR_INVALID_PARAMETER); 1936 1937 /* Leave the lock temporarily as the allocation might take long. */ 1936 * 1937 * Note! We leave the giant GMM lock temporarily as the allocation might 1938 * take a long time. gmmR0RegisterChunk reacquires it (ugly). 1939 */ 1938 1940 gmmR0MutexRelease(pGMM); 1939 if (enmChunkType == GMMCHUNKTYPE_NON_CONTINUOUS) 1940 rc = RTR0MemObjAllocPhysNC(&MemObj, GMM_CHUNK_SIZE, NIL_RTHCPHYS); 1941 else 1942 rc = RTR0MemObjAllocPhysEx(&MemObj, GMM_CHUNK_SIZE, NIL_RTHCPHYS, GMM_CHUNK_SIZE); 1943 1944 int rc2 = gmmR0MutexAcquire(pGMM); 1945 AssertRCReturn(rc2, rc2); 1946 1947 if (RT_SUCCESS(rc)) 1948 { 1949 rc = gmmR0RegisterChunk(pGMM, pSet, MemObj, hGVM, enmChunkType, ppChunk); 1950 if (RT_FAILURE(rc)) 1951 RTR0MemObjFree(MemObj, false /* fFreeMappings */); 1952 } 1941 1942 RTR0MEMOBJ hMemObj; 1943 int rc = RTR0MemObjAllocPhysNC(&hMemObj, GMM_CHUNK_SIZE, NIL_RTHCPHYS); 1953 1944 /** @todo Check that RTR0MemObjAllocPhysNC always returns VERR_NO_MEMORY on 1954 1945 * allocation failure. */ 1946 if (RT_SUCCESS(rc)) 1947 { 1948 rc = gmmR0RegisterChunk(pGMM, pSet, hMemObj, hGVM, 0 /*fChunkFlags*/, NULL); 1949 if (RT_SUCCESS(rc)) 1950 return rc; 1951 1952 RTR0MemObjFree(hMemObj, false /* fFreeMappings */); 1953 } 1954 1955 int rc2 = gmmR0MutexAcquire(pGMM); 1956 AssertRCReturn(rc2, RT_FAILURE(rc) ? rc : rc2); 1955 1957 return rc; 1956 1958 } … … 2001 2003 while (pSet->cFreePages < cPages) 2002 2004 { 2003 int rc = gmmR0AllocateOneChunk(pGMM, pSet, pGVM->hSelf , GMMCHUNKTYPE_NON_CONTINUOUS);2005 int rc = gmmR0AllocateOneChunk(pGMM, pSet, pGVM->hSelf); 2004 2006 if (RT_FAILURE(rc)) 2005 2007 return rc; … … 2034 2036 2035 2037 /* Allocate more. */ 2036 int rc = gmmR0AllocateOneChunk(pGMM, pSet, hGVM , GMMCHUNKTYPE_NON_CONTINUOUS);2038 int rc = gmmR0AllocateOneChunk(pGMM, pSet, hGVM); 2037 2039 if (RT_FAILURE(rc)) 2038 2040 return rc; … … 2636 2638 { 2637 2639 const unsigned cPages = (GMM_CHUNK_SIZE >> PAGE_SHIFT); 2638 PGMMCHUNK pChunk; 2639 GMMPAGEDESC PageDesc; 2640 2641 if (RT_UNLIKELY(pGVM->gmm.s.Allocated.cBasePages + pGVM->gmm.s.cBalloonedPages + cPages > pGVM->gmm.s.Reserved.cBasePages)) 2640 if (RT_UNLIKELY( pGVM->gmm.s.Allocated.cBasePages + pGVM->gmm.s.cBalloonedPages + cPages 2641 > pGVM->gmm.s.Reserved.cBasePages)) 2642 2642 { 2643 2643 Log(("GMMR0AllocateLargePage: Reserved=%#llx Allocated+Requested=%#llx+%#x!\n", … … 2647 2647 } 2648 2648 2649 /* Allocate a new continuous chunk. */ 2650 rc = gmmR0AllocateOneChunk(pGMM, &pGMM->Private, pGVM->hSelf, GMMCHUNKTYPE_CONTINUOUS, &pChunk); 2651 if (RT_FAILURE(rc)) 2652 { 2653 gmmR0MutexRelease(pGMM); 2654 return rc; 2655 } 2656 2657 /* Unlink the new chunk from the free list. */ 2658 gmmR0UnlinkChunk(pChunk); 2659 2660 /* Allocate all pages. */ 2661 gmmR0AllocatePage(pGMM, pGVM->hSelf, pChunk, &PageDesc); 2662 /* Return the first page as we'll use the whole chunk as one big page. */ 2663 *pIdPage = PageDesc.idPage; 2664 *pHCPhys = PageDesc.HCPhysGCPhys; 2665 2666 for (unsigned i = 1; i < cPages; i++) 2667 gmmR0AllocatePage(pGMM, pGVM->hSelf, pChunk, &PageDesc); 2668 2669 /* Update accounting. */ 2670 pGVM->gmm.s.Allocated.cBasePages += cPages; 2671 pGVM->gmm.s.cPrivatePages += cPages; 2672 pGMM->cAllocatedPages += cPages; 2673 2674 gmmR0LinkChunk(pChunk, &pGMM->Private); 2649 /* 2650 * Allocate a new large page chunk. 2651 * 2652 * Note! We leave the giant GMM lock temporarily as the allocation might 2653 * take a long time. gmmR0RegisterChunk will retake it (ugly). 2654 */ 2655 AssertCompile(GMM_CHUNK_SIZE == _2M); 2656 gmmR0MutexRelease(pGMM); 2657 2658 RTR0MEMOBJ hMemObj; 2659 rc = RTR0MemObjAllocPhysEx(&hMemObj, GMM_CHUNK_SIZE, NIL_RTHCPHYS, GMM_CHUNK_SIZE); 2660 if (RT_SUCCESS(rc)) 2661 { 2662 PGMMCHUNK pChunk; 2663 rc = gmmR0RegisterChunk(pGMM, &pGMM->Private, hMemObj, pGVM->hSelf, GMM_CHUNK_FLAGS_LARGE_PAGE, &pChunk); 2664 if (RT_SUCCESS(rc)) 2665 { 2666 /* 2667 * Allocate all the pages in the chunk. 2668 */ 2669 /* Unlink the new chunk from the free list. */ 2670 gmmR0UnlinkChunk(pChunk); 2671 2672 /** @todo rewrite this to skip the looping. */ 2673 /* Allocate all pages. */ 2674 GMMPAGEDESC PageDesc; 2675 gmmR0AllocatePage(pGMM, pGVM->hSelf, pChunk, &PageDesc); 2676 2677 /* Return the first page as we'll use the whole chunk as one big page. */ 2678 *pIdPage = PageDesc.idPage; 2679 *pHCPhys = PageDesc.HCPhysGCPhys; 2680 2681 for (unsigned i = 1; i < cPages; i++) 2682 gmmR0AllocatePage(pGMM, pGVM->hSelf, pChunk, &PageDesc); 2683 2684 /* Update accounting. */ 2685 pGVM->gmm.s.Allocated.cBasePages += cPages; 2686 pGVM->gmm.s.cPrivatePages += cPages; 2687 pGMM->cAllocatedPages += cPages; 2688 2689 gmmR0LinkChunk(pChunk, &pGMM->Private); 2690 gmmR0MutexRelease(pGMM); 2691 } 2692 else 2693 RTR0MemObjFree(hMemObj, false /* fFreeMappings */); 2694 } 2675 2695 } 2676 2696 else 2697 { 2698 gmmR0MutexRelease(pGMM); 2677 2699 rc = VERR_INTERNAL_ERROR_5; 2678 2679 gmmR0MutexRelease(pGMM); 2700 } 2701 2680 2702 LogFlow(("GMMR0AllocateLargePage: returns %Rrc\n", rc)); 2681 2703 return rc; … … 3847 3869 3848 3870 /* 3849 * Lock the memory before taking the semaphore. 3871 * Lock the memory and add it as new chunk with our hGVM. 3872 * (The GMM locking is done inside gmmR0RegisterChunk.) 3850 3873 */ 3851 3874 RTR0MEMOBJ MemObj; … … 3853 3876 if (RT_SUCCESS(rc)) 3854 3877 { 3855 /* Grab the lock. */ 3856 rc = gmmR0MutexAcquire(pGMM); 3878 rc = gmmR0RegisterChunk(pGMM, &pGMM->Private, MemObj, pGVM->hSelf, 0 /*fChunkFlags*/, NULL); 3857 3879 if (RT_SUCCESS(rc)) 3858 {3859 /*3860 * Add a new chunk with our hGVM.3861 */3862 rc = gmmR0RegisterChunk(pGMM, &pGMM->Private, MemObj, pGVM->hSelf, GMMCHUNKTYPE_NON_CONTINUOUS);3863 3880 gmmR0MutexRelease(pGMM); 3864 } 3865 3866 if (RT_FAILURE(rc)) 3881 else 3867 3882 RTR0MemObjFree(MemObj, false /* fFreeMappings */); 3868 3883 } … … 3871 3886 return rc; 3872 3887 } 3888 3873 3889 3874 3890 typedef struct
Note:
See TracChangeset
for help on using the changeset viewer.