Index: /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c	(revision 41651)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c	(revision 41652)
@@ -68,4 +68,7 @@
      *  allocation. */
     bool                fLargePage;
+    /** Whether we have individual pages or a kernel-mapped virtual memory block in
+     *  an RTR0MEMOBJTYPE_PHYS_NC allocation. */
+    bool                fIndivPages;
 } RTR0MEMOBJSOL, *PRTR0MEMOBJSOL;
 
@@ -154,5 +157,6 @@
     {
         /*
-         * Lock this page into memory "long term" to prevent paging out of this page.
+         * Lock this page into memory "long term" to prevent paging out of this page
+         * when we drop the page lock temporarily (during free).
          */
         page_pp_lock(pPage, 0 /* COW */, 1 /* Kernel */);
@@ -169,5 +173,4 @@
  * Allocates physical, non-contiguous memory of pages.
  *
- * @param uPhysHi   The upper physical address limit (inclusive).
  * @param puPhys    Where to store the physical address of first page. Optional,
  *                  can be NULL.
@@ -176,5 +179,5 @@
  * @return Array of allocated pages, NULL on failure.
  */
-static page_t **rtR0MemObjSolPagesAlloc(uint64_t uPhysHi, uint64_t *puPhys, size_t cb)
+static page_t **rtR0MemObjSolPagesAlloc(uint64_t *puPhys, size_t cb)
 {
     /*
@@ -191,5 +194,5 @@
      * Non-pageable memory reservation request for _4K pages, don't sleep.
      */
-    pgcnt_t cPages = (cb + PAGE_SIZE - 1) >> PAGE_SHIFT;
+    size_t cPages = (cb + PAGE_SIZE - 1) >> PAGE_SHIFT;
     int rc = page_resv(cPages, KM_NOSLEEP);
     if (rc)
@@ -203,42 +206,13 @@
              * we don't yet have the 'virtAddr' to which this memory may be mapped.
              */
-            caddr_t virtAddr = NULL;
+            caddr_t virtAddr = 0;
             for (size_t i = 0; i < cPages; i++, virtAddr += PAGE_SIZE)
             {
-                uint32_t cTries = 3;
-                page_t *pPage   = NULL;
-                while (cTries > 0)
-                {
-                    /*
-                     * Get a page from the free list locked exclusively. The page will be named (hashed in)
-                     * and we rely on it during free. Downgrade the page to a shared lock to prevent the page
-                     * from being relocated.
-                     */
-                    pPage = rtR0MemObjSolPageAlloc(virtAddr, PAGE_SIZE);
-                    if (!pPage)
-                        break;
-
-                    /*
-                     * Check if the physical address backing the page is within the requested range if any.
-                     * If it isn't, discard the page and try again.
-                     */
-                    /** @todo Remove this constraint here, force all high-limit applicable cases
-                     *        through rtR0SolMemAlloc() */
-                    if (uPhysHi != NIL_RTHCPHYS)
-                    {
-                        uint64_t uPhys = rtR0MemObjSolPagePhys(pPage);
-                        if (uPhys > uPhysHi)
-                        {
-                            page_destroy(pPage, 0 /* move it to the free list */);
-                            pPage = NULL;
-                            --cTries;
-                            continue;
-                        }
-                    }
-
-                    ppPages[i] = pPage;
-                    break;
-                }
-
+                /*
+                 * Get a page from the free list locked exclusively. The page will be named (hashed in)
+                 * and we rely on it during free. Downgrade the page to a shared lock to prevent the page
+                 * from being relocated.
+                 */
+                page_t *pPage = rtR0MemObjSolPageAlloc(virtAddr, PAGE_SIZE);
                 if (RT_UNLIKELY(!pPage))
                 {
@@ -252,4 +226,6 @@
                     return NULL;
                 }
+
+                ppPages[i] = pPage;
             }
 
@@ -595,5 +571,8 @@
 
         case RTR0MEMOBJTYPE_PHYS_NC:
-            rtR0MemObjSolPagesFree(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
+            if (pMemSolaris->fIndivPages)
+                rtR0MemObjSolPagesFree(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
+            else
+                rtR0SolMemFree(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
             break;
 
@@ -688,19 +667,46 @@
         return VERR_NO_MEMORY;
 
-    uint64_t PhysAddr = UINT64_MAX;
-    void *pvPages = rtR0MemObjSolPagesAlloc((uint64_t)PhysHighest, &PhysAddr, cb);
-    if (!pvPages)
-    {
-        LogRel(("rtR0MemObjNativeAllocPhysNC: rtR0MemObjSolPagesAlloc failed for cb=%u.\n", cb));
-        rtR0MemObjDelete(&pMemSolaris->Core);
-        return VERR_NO_MEMORY;
-    }
-    pMemSolaris->Core.pv   = NULL;
-    pMemSolaris->pvHandle  = pvPages;
-
-    Assert(PhysAddr != UINT64_MAX);
-    Assert(!(PhysAddr & PAGE_OFFSET_MASK));
-    *ppMem = &pMemSolaris->Core;
-    return VINF_SUCCESS;
+    if (PhysHighest == NIL_RTHCPHYS)
+    {
+        uint64_t PhysAddr = UINT64_MAX;
+        void *pvPages = rtR0MemObjSolPagesAlloc(&PhysAddr, cb);
+        if (!pvPages)
+        {
+            LogRel(("rtR0MemObjNativeAllocPhysNC: rtR0MemObjSolPagesAlloc failed for cb=%u.\n", cb));
+            rtR0MemObjDelete(&pMemSolaris->Core);
+            return VERR_NO_MEMORY;
+        }
+        Assert(PhysAddr != UINT64_MAX);
+        Assert(!(PhysAddr & PAGE_OFFSET_MASK));
+
+        pMemSolaris->Core.pv     = NULL;
+        pMemSolaris->pvHandle    = pvPages;
+        pMemSolaris->fIndivPages = true;
+        *ppMem = &pMemSolaris->Core;
+        return VINF_SUCCESS;
+    }
+    else
+    {
+        /*
+         * If we must satisfy an upper limit constraint, it isn't feasible to grab individual pages.
+         * We fall back to using contig_alloc().
+         */
+        uint64_t PhysAddr = UINT64_MAX;
+        void *pvMem = rtR0SolMemAlloc(PhysHighest, &PhysAddr, cb, PAGE_SIZE, false /* fContig */);
+        if (!pvMem)
+        {
+            LogRel(("rtR0MemObjNativeAllocPhysNC: rtR0SolMemAlloc failed for cb=%u PhysHighest=%RHp.\n", cb, PhysHighest));
+            rtR0MemObjDelete(&pMemSolaris->Core);
+            return VERR_NO_MEMORY;
+        }
+        Assert(PhysAddr != UINT64_MAX);
+        Assert(!(PhysAddr & PAGE_OFFSET_MASK));
+
+        pMemSolaris->Core.pv     = pvMem;
+        pMemSolaris->pvHandle    = NULL;
+        pMemSolaris->fIndivPages = false;
+        *ppMem = &pMemSolaris->Core;
+        return VINF_SUCCESS;
+    }
 
 #else /* 32 bit: */
@@ -1001,7 +1007,9 @@
          * Prepare the pages for mapping according to type.
          */
-        if (pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS_NC)
+        if (   pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS_NC
+            && pMemToMapSolaris->fIndivPages)
         {
             page_t **ppPages = pMemToMapSolaris->pvHandle;
+            AssertPtr(ppPages);
             for (size_t iPage = 0; iPage < cPages; iPage++)
                 paPhysAddrs[iPage] = rtR0MemObjSolPagePhys(ppPages[iPage]);
@@ -1086,5 +1094,6 @@
     {
         case RTR0MEMOBJTYPE_PHYS_NC:
-            if (pMemSolaris->Core.u.Phys.fAllocated)
+            if (   pMemSolaris->Core.u.Phys.fAllocated
+                || !pMemSolaris->fIndivPages)
             {
                 uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
