Index: /trunk/src/VBox/VMM/VMMR0/GMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/GMMR0.cpp	(revision 82875)
+++ /trunk/src/VBox/VMM/VMMR0/GMMR0.cpp	(revision 82876)
@@ -107,4 +107,10 @@
  * by the VM that locked it. We will make no attempt at implementing
  * page sharing on these systems, just do enough to make it all work.
+ *
+ * @note With 6.1 really dropping 32-bit support, the legacy mode is obsoleted
+ *       under the assumption that there is sufficient kernel virtual address
+ *       space to map all of the guest memory allocations.  So, we'll be using
+ *       #RTR0MemObjAllocPage on some platforms as an alternative to
+ *       #RTR0MemObjAllocPhysNC.
  *
  *
@@ -186,4 +192,7 @@
 # define VBOX_USE_CRIT_SECT_FOR_GIANT
 #endif
+
+/** Enable the legacy mode code (will be dropped soon). */
+#define GMM_WITH_LEGACY_MODE
 
 
@@ -450,6 +459,8 @@
 /** Indicates that the chunk is a large page (2MB). */
 #define GMM_CHUNK_FLAGS_LARGE_PAGE  UINT16_C(0x0001)
+#ifdef GMM_WITH_LEGACY_MODE
 /** Indicates that the chunk was locked rather than allocated directly. */
-#define GMM_CHUNK_FLAGS_SEEDED      UINT16_C(0x0002)
+# define GMM_CHUNK_FLAGS_SEEDED     UINT16_C(0x0002)
+#endif
 /** @}  */
 
@@ -550,7 +561,16 @@
     uint64_t            cBalloonedPages;
 
+#ifndef GMM_WITH_LEGACY_MODE
+# ifdef VBOX_WITH_LINEAR_HOST_PHYS_MEM
+    /** Whether #RTR0MemObjAllocPhysNC works.   */
+    bool                fHasWorkingAllocPhysNC;
+# else
+    bool                fPadding;
+# endif
+#else
     /** The legacy allocation mode indicator.
      * This is determined at initialization time. */
     bool                fLegacyAllocationMode;
+#endif
     /** The bound memory mode indicator.
      * When set, the memory will be bound to a specific VM and never
@@ -799,8 +819,29 @@
         if (RT_SUCCESS(rc))
         {
+#ifndef GMM_WITH_LEGACY_MODE
+            /*
+             * Figure out how we're going to allocate stuff (only applicable to
+             * host with linear physical memory mappings).
+             */
+            pGMM->fBoundMemoryMode = false;
+# ifdef VBOX_WITH_LINEAR_HOST_PHYS_MEM
+            pGMM->fHasWorkingAllocPhysNC = false;
+
+            RTR0MEMOBJ hMemObj;
+            rc = RTR0MemObjAllocPhysNC(&hMemObj, GMM_CHUNK_SIZE, NIL_RTHCPHYS);
+            if (RT_SUCCESS(rc))
+            {
+                rc = RTR0MemObjFree(hMemObj, true);
+                AssertRC(rc);
+                pGMM->fHasWorkingAllocPhysNC = true;
+            }
+            else if (rc != VERR_NOT_SUPPORTED)
+                SUPR0Printf("GMMR0Init: Warning! RTR0MemObjAllocPhysNC(, %u, NIL_RTHCPHYS) -> %d!\n", GMM_CHUNK_SIZE, rc);
+# endif
+#else /* GMM_WITH_LEGACY_MODE */
             /*
              * Check and see if RTR0MemObjAllocPhysNC works.
              */
-#if 0 /* later, see @bufref{3170}. */
+# if 0 /* later, see @bufref{3170}. */
             RTR0MEMOBJ MemObj;
             rc = RTR0MemObjAllocPhysNC(&MemObj, _64K, NIL_RTHCPHYS);
@@ -814,19 +855,20 @@
             else
                 SUPR0Printf("GMMR0Init: RTR0MemObjAllocPhysNC(,64K,Any) -> %d!\n", rc);
-#else
-# if defined(RT_OS_WINDOWS) || (defined(RT_OS_SOLARIS) && ARCH_BITS == 64) || defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
+# else
+#  if defined(RT_OS_WINDOWS) || (defined(RT_OS_SOLARIS) && ARCH_BITS == 64) || defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
             pGMM->fLegacyAllocationMode = false;
-#  if ARCH_BITS == 32
+#   if ARCH_BITS == 32
             /* Don't reuse possibly partial chunks because of the virtual
                address space limitation. */
             pGMM->fBoundMemoryMode      = true;
+#   else
+            pGMM->fBoundMemoryMode      = false;
+#   endif
 #  else
-            pGMM->fBoundMemoryMode      = false;
-#  endif
-# else
             pGMM->fLegacyAllocationMode = true;
             pGMM->fBoundMemoryMode      = true;
+#  endif
 # endif
-#endif
+#endif /* GMM_WITH_LEGACY_MODE */
 
             /*
@@ -836,5 +878,11 @@
 
             g_pGMM = pGMM;
+#ifdef GMM_WITH_LEGACY_MODE
             LogFlow(("GMMInit: pGMM=%p fLegacyAllocationMode=%RTbool fBoundMemoryMode=%RTbool\n", pGMM, pGMM->fLegacyAllocationMode, pGMM->fBoundMemoryMode));
+#elif defined(VBOX_WITH_LINEAR_HOST_PHYS_MEM)
+            LogFlow(("GMMInit: pGMM=%p fBoundMemoryMode=%RTbool fHasWorkingAllocPhysNC=%RTbool\n", pGMM, pGMM->fBoundMemoryMode, pGMM->fHasWorkingAllocPhysNC));
+#else
+            LogFlow(("GMMInit: pGMM=%p fBoundMemoryMode=%RTbool\n", pGMM, pGMM->fBoundMemoryMode));
+#endif
             return VINF_SUCCESS;
         }
@@ -2133,5 +2181,9 @@
     Assert(pGMM->hMtxOwner != RTThreadNativeSelf());
     Assert(hGVM != NIL_GVM_HANDLE || pGMM->fBoundMemoryMode);
+#ifdef GMM_WITH_LEGACY_MODE
     Assert(fChunkFlags == 0 || fChunkFlags == GMM_CHUNK_FLAGS_LARGE_PAGE || fChunkFlags == GMM_CHUNK_FLAGS_SEEDED);
+#else
+    Assert(fChunkFlags == 0 || fChunkFlags == GMM_CHUNK_FLAGS_LARGE_PAGE);
+#endif
 
 #if defined(VBOX_WITH_RAM_IN_KERNEL) && !defined(VBOX_WITH_LINEAR_HOST_PHYS_MEM)
@@ -2139,5 +2191,9 @@
      * Get a ring-0 mapping of the object.
      */
+# ifdef GMM_WITH_LEGACY_MODE
     uint8_t *pbMapping = !(fChunkFlags & GMM_CHUNK_FLAGS_SEEDED) ? (uint8_t *)RTR0MemObjAddress(hMemObj) : NULL;
+# else
+    uint8_t *pbMapping = (uint8_t *)RTR0MemObjAddress(hMemObj);
+# endif
     if (!pbMapping)
     {
@@ -2242,5 +2298,15 @@
 
     RTR0MEMOBJ hMemObj;
+#ifndef GMM_WITH_LEGACY_MODE
+    int rc;
+# ifdef VBOX_WITH_LINEAR_HOST_PHYS_MEM
+    if (pGMM->fHasWorkingAllocPhysNC)
+        rc = RTR0MemObjAllocPhysNC(&hMemObj, GMM_CHUNK_SIZE, NIL_RTHCPHYS);
+    else
+# endif
+        rc = RTR0MemObjAllocPage(&hMemObj, GMM_CHUNK_SIZE, false /*fExecutable*/);
+#else
     int rc = RTR0MemObjAllocPhysNC(&hMemObj, GMM_CHUNK_SIZE, NIL_RTHCPHYS);
+#endif
     if (RT_SUCCESS(rc))
     {
@@ -2574,4 +2640,5 @@
     }
 
+#ifdef GMM_WITH_LEGACY_MODE
     /*
      * If we're in legacy memory mode, it's easy to figure if we have
@@ -2584,4 +2651,5 @@
         return VERR_GMM_SEED_ME;
     }
+#endif
 
     /*
@@ -2600,18 +2668,20 @@
     pGMM->cAllocatedPages           += cPages;
 
+#ifdef GMM_WITH_LEGACY_MODE
     /*
      * Part two of it's-easy-in-legacy-memory-mode.
      */
-    uint32_t iPage = 0;
     if (pGMM->fLegacyAllocationMode)
     {
-        iPage = gmmR0AllocatePagesInBoundMode(pGVM, iPage, cPages, paPages);
+        uint32_t iPage = gmmR0AllocatePagesInBoundMode(pGVM, 0, cPages, paPages);
         AssertReleaseReturn(iPage == cPages, VERR_GMM_ALLOC_PAGES_IPE);
         return VINF_SUCCESS;
     }
+#endif
 
     /*
      * Bound mode is also relatively straightforward.
      */
+    uint32_t iPage = 0;
     int rc = VINF_SUCCESS;
     if (pGMM->fBoundMemoryMode)
@@ -3069,7 +3139,9 @@
         return rc;
 
+#ifdef GMM_WITH_LEGACY_MODE
     // /* Not supported in legacy mode where we allocate the memory in ring 3 and lock it in ring 0. */
     // if (pGMM->fLegacyAllocationMode)
     //     return VERR_NOT_SUPPORTED;
+#endif
 
     *pHCPhys = NIL_RTHCPHYS;
@@ -3170,7 +3242,9 @@
         return rc;
 
+#ifdef GMM_WITH_LEGACY_MODE
     // /* Not supported in legacy mode where we allocate the memory in ring 3 and lock it in ring 0. */
     // if (pGMM->fLegacyAllocationMode)
     //     return VERR_NOT_SUPPORTED;
+#endif
 
     gmmR0MutexAcquire(pGMM);
@@ -3259,5 +3333,7 @@
      */
     if (    pChunk->cMappingsX
+#ifdef GMM_WITH_LEGACY_MODE
         &&  (!pGMM->fLegacyAllocationMode || (pChunk->fFlags & GMM_CHUNK_FLAGS_LARGE_PAGE))
+#endif
         &&  pGVM)
         gmmR0UnmapChunkLocked(pGMM, pGVM, pChunk);
@@ -3387,8 +3463,13 @@
      */
     /** @todo Do this on the way out. */
-    if (RT_UNLIKELY(   pChunk->cFree == GMM_CHUNK_NUM_PAGES
-                    && pChunk->pFreeNext
-                    && pChunk->pFreePrev /** @todo this is probably misfiring, see reset... */
-                    && (!pGMM->fLegacyAllocationMode || (pChunk->fFlags & GMM_CHUNK_FLAGS_LARGE_PAGE))))
+    if (RT_LIKELY(   pChunk->cFree != GMM_CHUNK_NUM_PAGES
+                  || pChunk->pFreeNext == NULL
+                  || pChunk->pFreePrev == NULL /** @todo this is probably misfiring, see reset... */))
+    { /* likely */ }
+#ifdef GMM_WITH_LEGACY_MODE
+    else if (RT_LIKELY(pGMM->fLegacyAllocationMode && !(pChunk->fFlags & GMM_CHUNK_FLAGS_LARGE_PAGE)))
+    { /* likely */ }
+#endif
+    else
         gmmR0FreeChunk(pGMM, NULL, pChunk, false);
 
@@ -3913,5 +3994,8 @@
 static int gmmR0UnmapChunkLocked(PGMM pGMM, PGVM pGVM, PGMMCHUNK pChunk)
 {
-    Assert(!pGMM->fLegacyAllocationMode || (pChunk->fFlags & GMM_CHUNK_FLAGS_LARGE_PAGE)); NOREF(pGMM);
+    RT_NOREF_PV(pGMM);
+#ifdef GMM_WITH_LEGACY_MODE
+    Assert(!pGMM->fLegacyAllocationMode || (pChunk->fFlags & GMM_CHUNK_FLAGS_LARGE_PAGE));
+#endif
 
     /*
@@ -3959,6 +4043,8 @@
 static int gmmR0UnmapChunk(PGMM pGMM, PGVM pGVM, PGMMCHUNK pChunk, bool fRelaxedSem)
 {
+#ifdef GMM_WITH_LEGACY_MODE
     if (!pGMM->fLegacyAllocationMode || (pChunk->fFlags & GMM_CHUNK_FLAGS_LARGE_PAGE))
     {
+#endif
         /*
          * Lock the chunk and if possible leave the giant GMM lock.
@@ -3973,4 +4059,5 @@
         }
         return rc;
+#ifdef GMM_WITH_LEGACY_MODE
     }
 
@@ -3980,4 +4067,5 @@
     Log(("gmmR0UnmapChunk: Chunk %#x is not mapped into pGVM=%p/%#x (legacy)\n", pChunk->Core.Key, pGVM, pGVM->hSelf));
     return VERR_GMM_CHUNK_NOT_MAPPED;
+#endif
 }
 
@@ -3996,4 +4084,5 @@
 static int gmmR0MapChunkLocked(PGMM pGMM, PGVM pGVM, PGMMCHUNK pChunk, PRTR3PTR ppvR3)
 {
+#ifdef GMM_WITH_LEGACY_MODE
     /*
      * If we're in legacy mode this is simple.
@@ -4010,4 +4099,7 @@
         return VINF_SUCCESS;
     }
+#else
+    RT_NOREF(pGMM);
+#endif
 
     /*
@@ -4266,4 +4358,5 @@
 GMMR0DECL(int) GMMR0SeedChunk(PGVM pGVM, VMCPUID idCpu, RTR3PTR pvR3)
 {
+#ifdef GMM_WITH_LEGACY_MODE
     /*
      * Validate input and get the basics.
@@ -4301,4 +4394,8 @@
     LogFlow(("GMMR0SeedChunk: rc=%d (pvR3=%p)\n", rc, pvR3));
     return rc;
+#else
+    RT_NOREF(pGVM, idCpu, pvR3);
+    return VERR_NOT_SUPPORTED;
+#endif
 }
 
