Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 40967)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 40968)
@@ -1894,26 +1894,23 @@
 	r0drv/powernotification-r0drv.c \
 	r0drv/solaris/RTLogWriteDebugger-r0drv-solaris.c \
+	r0drv/solaris/RTMpPokeCpu-r0drv-solaris.c \
+	r0drv/solaris/alloc-r0drv-solaris.c \
 	r0drv/solaris/assert-r0drv-solaris.c \
 	r0drv/solaris/dbg-r0drv-solaris.c \
 	r0drv/solaris/initterm-r0drv-solaris.c \
 	r0drv/solaris/memuserkernel-r0drv-solaris.c \
+	r0drv/solaris/mpnotification-r0drv-solaris.c \
+	r0drv/solaris/memobj-r0drv-solaris.c \
+	r0drv/solaris/mp-r0drv-solaris.c \
+	r0drv/solaris/process-r0drv-solaris.c \
 	r0drv/solaris/semevent-r0drv-solaris.c \
 	r0drv/solaris/semeventmulti-r0drv-solaris.c \
 	r0drv/solaris/semfastmutex-r0drv-solaris.c \
 	r0drv/solaris/semmutex-r0drv-solaris.c \
-	r0drv/solaris/spinlock-r0drv-solaris.c
-
- # VBI is now compiled into IPRT
- RuntimeR0Drv_SOURCES.solaris += \
-	r0drv/solaris/vbi/RTMpPokeCpu-r0drv-solaris.c \
-	r0drv/solaris/vbi/mpnotification-r0drv-solaris.c \
- 	r0drv/solaris/vbi/alloc-r0drv-solaris.c \
- 	r0drv/solaris/vbi/memobj-r0drv-solaris.c \
- 	r0drv/solaris/vbi/mp-r0drv-solaris.c \
- 	r0drv/solaris/vbi/process-r0drv-solaris.c \
- 	r0drv/solaris/vbi/thread-r0drv-solaris.c \
- 	r0drv/solaris/vbi/thread2-r0drv-solaris.c \
- 	r0drv/solaris/vbi/time-r0drv-solaris.c \
- 	r0drv/solaris/vbi/timer-r0drv-solaris.c
+	r0drv/solaris/spinlock-r0drv-solaris.c \
+	r0drv/solaris/thread-r0drv-solaris.c \
+	r0drv/solaris/thread2-r0drv-solaris.c \
+	r0drv/solaris/time-r0drv-solaris.c \
+	r0drv/solaris/timer-r0drv-solaris.c
 
 
Index: /trunk/src/VBox/Runtime/r0drv/solaris/RTMpPokeCpu-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/RTMpPokeCpu-r0drv-solaris.c	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/RTMpPokeCpu-r0drv-solaris.c	(revision 40968)
@@ -0,0 +1,50 @@
+/* $Id$ */
+/** @file
+ * IPRT - RTMpPokeCpu, Solaris Implementation.
+ */
+
+/*
+ * Copyright (C) 2009 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/mp.h>
+
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/assert.h>
+#include <iprt/err.h>
+
+
+
+RTDECL(int) RTMpPokeCpu(RTCPUID idCpu)
+{
+    RT_ASSERT_INTS_ON();
+    if (idCpu < ncpus)
+        poke_cpu(idCpu);
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/solaris/alloc-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/alloc-r0drv-solaris.c	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/alloc-r0drv-solaris.c	(revision 40968)
@@ -0,0 +1,206 @@
+/* $Id$ */
+/** @file
+ * IPRT - Memory Allocation, Ring-0 Driver, Solaris.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/mem.h>
+
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/log.h>
+#include <iprt/param.h>
+#include <iprt/thread.h>
+#include "r0drv/alloc-r0drv.h"
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+static ddi_dma_attr_t s_rtR0SolDmaAttr =
+{
+    DMA_ATTR_V0,                /* Version Number */
+    (uint64_t)0,                /* Lower limit */
+    (uint64_t)0,                /* High limit */
+    (uint64_t)0xffffffff,       /* Counter limit */
+    (uint64_t)PAGESIZE,         /* Alignment */
+    (uint64_t)PAGESIZE,         /* Burst size */
+    (uint64_t)PAGESIZE,         /* Effective DMA size */
+    (uint64_t)0xffffffff,       /* Max DMA xfer size */
+    (uint64_t)0xffffffff,       /* Segment boundary */
+    1,                          /* Scatter-gather list length (1 for contiguous) */
+    1,                          /* Device granularity */
+    0                           /* Bus-specific flags */
+};
+
+extern void *contig_alloc(size_t cb, ddi_dma_attr_t *pDmaAttr, size_t uAlign, int fCanSleep);
+
+
+/**
+ * OS specific allocation function.
+ */
+DECLHIDDEN(int) rtR0MemAllocEx(size_t cb, uint32_t fFlags, PRTMEMHDR *ppHdr)
+{
+    size_t      cbAllocated = cb;
+    PRTMEMHDR   pHdr;
+
+#ifdef RT_ARCH_AMD64
+    if (fFlags & RTMEMHDR_FLAG_EXEC)
+    {
+        AssertReturn(!(fFlags & RTMEMHDR_FLAG_ANY_CTX), NULL);
+        cbAllocated = RT_ALIGN_Z(cb + sizeof(*pHdr), PAGE_SIZE) - sizeof(*pHdr);
+        pHdr = (PRTMEMHDR)segkmem_alloc(heaptext_arena, cbAllocated + sizeof(*pHdr), KM_SLEEP);
+    }
+    else
+#endif
+    {
+        unsigned fKmFlags = fFlags & RTMEMHDR_FLAG_ANY_CTX_ALLOC ? KM_NOSLEEP : KM_SLEEP;
+        if (fFlags & RTMEMHDR_FLAG_ZEROED)
+            pHdr = (PRTMEMHDR)kmem_zalloc(cb + sizeof(*pHdr), fKmFlags);
+        else
+            pHdr = (PRTMEMHDR)kmem_alloc(cb + sizeof(*pHdr), fKmFlags);
+    }
+    if (RT_UNLIKELY(!pHdr))
+    {
+        LogRel(("rtMemAllocEx(%u, %#x) failed\n", (unsigned)cb + sizeof(*pHdr), fFlags));
+        return VERR_NO_MEMORY;
+    }
+
+    pHdr->u32Magic  = RTMEMHDR_MAGIC;
+    pHdr->fFlags    = fFlags;
+    pHdr->cb        = cbAllocated;
+    pHdr->cbReq     = cb;
+
+    *ppHdr = pHdr;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * OS specific free function.
+ */
+DECLHIDDEN(void) rtR0MemFree(PRTMEMHDR pHdr)
+{
+    pHdr->u32Magic += 1;
+#ifdef RT_ARCH_AMD64
+    if (pHdr->fFlags & RTMEMHDR_FLAG_EXEC)
+        segkmem_free(heaptext_arena, pHdr, pHdr->cb + sizeof(*pHdr));
+    else
+#endif
+        kmem_free(pHdr, pHdr->cb + sizeof(*pHdr));
+}
+
+
+/**
+ * Allocates physical memory which satisfy the given constraints.
+ *
+ * @param   uPhysHi        The upper physical address limit (inclusive).
+ * @param   puPhys         Where to store the physical address of the allocated
+ *                         memory. Optional, can be NULL.
+ * @param   cb             Size of allocation.
+ * @param   uAlignment     Alignment.
+ * @param   fContig        Whether the memory must be physically contiguous or
+ *                         not.
+ *
+ * @returns Virtual address of allocated memory block or NULL if allocation
+ *        failed.
+ */
+DECLHIDDEN(void *) rtR0SolMemAlloc(uint64_t uPhysHi, uint64_t *puPhys, size_t cb, uint64_t uAlignment, bool fContig)
+{
+    if ((cb & PAGEOFFSET) != 0)
+        return NULL;
+
+    size_t cPages = (cb + PAGESIZE - 1) >> PAGESHIFT;
+    if (!cPages)
+        return NULL;
+
+    ddi_dma_attr_t DmaAttr = s_rtR0SolDmaAttr;
+    DmaAttr.dma_attr_addr_hi    = uPhysHi;
+    DmaAttr.dma_attr_align      = uAlignment;
+    if (!fContig)
+        DmaAttr.dma_attr_sgllen = cPages > INT_MAX ? INT_MAX - 1 : cPages;
+    else
+        AssertRelease(DmaAttr.dma_attr_sgllen == 1);
+
+    void *pvMem = contig_alloc(cb, &DmaAttr, PAGESIZE, 1 /* can sleep */);
+    if (!pvMem)
+    {
+        LogRel(("rtR0SolMemAlloc failed. cb=%u Align=%u fContig=%d\n", (unsigned)cb, (unsigned)uAlignment, fContig));
+        return NULL;
+    }
+
+    pfn_t PageFrameNum = hat_getpfnum(kas.a_hat, (caddr_t)pvMem);
+    AssertRelease(PageFrameNum != PFN_INVALID);
+    if (puPhys)
+        *puPhys = (uint64_t)PageFrameNum << PAGESHIFT;
+
+    return pvMem;
+}
+
+
+/**
+ * Frees memory allocated using rtR0SolMemAlloc().
+ *
+ * @param   pv         The memory to free.
+ * @param   cb         Size of the memory block
+ */
+DECLHIDDEN(void) rtR0SolMemFree(void *pv, size_t cb)
+{
+    if (RT_LIKELY(pv))
+        g_pfnrtR0Sol_contig_free(pv, cb);
+}
+
+
+RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb)
+{
+    AssertPtrReturn(pPhys, NULL);
+    AssertReturn(cb > 0, NULL);
+    RT_ASSERT_PREEMPTIBLE();
+
+    /* Allocate physically contiguous (< 4GB) page-aligned memory. */
+    uint64_t uPhys;
+    void *pvMem = rtR0SolMemAlloc((uint64_t)_4G - 1, &uPhys, cb, PAGESIZE, true);
+    if (RT_UNLIKELY(!pvMem))
+    {
+        LogRel(("RTMemContAlloc failed to allocate %u bytes\n", cb));
+        return NULL;
+    }
+
+    Assert(uPhys < _4G);
+    *pPhys = uPhys;
+    return pvMem;
+}
+
+
+RTR0DECL(void) RTMemContFree(void *pv, size_t cb)
+{
+    RT_ASSERT_PREEMPTIBLE();
+    rtR0SolMemFree(pv, cb);
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.c	(revision 40968)
@@ -0,0 +1,1051 @@
+/* $Id$ */
+/** @file
+ * IPRT - Ring-0 Memory Objects, Solaris.
+ */
+
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/memobj.h>
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/log.h>
+#include <iprt/mem.h>
+#include <iprt/param.h>
+#include <iprt/process.h>
+#include "internal/memobj.h"
+#include "memobj-r0drv-solaris.h"
+
+#define SOL_IS_KRNL_ADDR(vx)    ((uintptr_t)(vx) >= kernelbase)
+static vnode_t                  s_PageVnode;
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * The Solaris version of the memory object structure.
+ */
+typedef struct RTR0MEMOBJSOL
+{
+    /** The core structure. */
+    RTR0MEMOBJINTERNAL  Core;
+    /** Pointer to kernel memory cookie. */
+    ddi_umem_cookie_t   Cookie;
+    /** Shadow locked pages. */
+    void               *pvHandle;
+    /** Access during locking. */
+    int                 fAccess;
+    /** Set if large pages are involved in an RTR0MEMOBJTYPE_PHYS
+     *  allocation. */
+    bool                fLargePage;
+} RTR0MEMOBJSOL, *PRTR0MEMOBJSOL;
+
+
+/**
+ * Returns the physical address for a virtual address.
+ *
+ * @param pv        The virtual address.
+ *
+ * @returns The physical address corresponding to @a pv.
+ */
+static uint64_t rtR0MemObjSolVirtToPhys(void *pv)
+{
+    struct hat *pHat         = NULL;
+    pfn_t       PageFrameNum = 0;
+    uintptr_t   uVirtAddr    = (uintptr_t)pv;
+
+    if (SOL_IS_KRNL_ADDR(pv))
+        pHat = kas.a_hat;
+    else
+    {
+        proc_t *pProcess = (proc_t *)RTR0ProcHandleSelf();
+        AssertRelease(pProcess);
+        pHat = pProcess->p_as->a_hat;
+    }
+
+    PageFrameNum = hat_getpfnum(pHat, (caddr_t)(uVirtAddr & PAGEMASK));
+    AssertReleaseMsg(PageFrameNum != PFN_INVALID, ("rtR0MemObjSolVirtToPhys failed. pv=%p\n", pv));
+    return (((uint64_t)PageFrameNum << PAGESHIFT) | (uVirtAddr & PAGEOFFSET));
+}
+
+
+/**
+ * Returns the physical address of a page from an array of pages.
+ *
+ * @param ppPages       The array of pages.
+ * @param iPage         Index of the page in the array to get the physical
+ *                      address.
+ *
+ * @returns Physical address of specific page within the list of pages specified
+ *         in @a ppPages.
+ */
+static inline uint64_t rtR0MemObjSolPageToPhys(page_t **ppPages, size_t iPage)
+{
+    pfn_t PageFrameNum = page_pptonum(ppPages[iPage]);
+    AssertReleaseMsg(PageFrameNum != PFN_INVALID, ("rtR0MemObjSolPageToPhys failed. ppPages=%p iPage=%u\n", ppPages, iPage));
+    return (uint64_t)PageFrameNum << PAGESHIFT;
+}
+
+
+/**
+ * Retreives a free page from the kernel freelist.
+ *
+ * @param virtAddr       The virtual address to which this page maybe mapped in
+ *                       the future.
+ * @param cbPage         The size of the page.
+ *
+ * @returns Pointer to the allocated page, NULL on failure.
+ */
+static page_t *rtR0MemObjSolPageFromFreelist(caddr_t virtAddr, size_t cbPage)
+{
+    seg_t KernelSeg;
+    KernelSeg.s_as = &kas;
+    page_t *pPage = page_get_freelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
+                                      cbPage, 0 /* flags */, NULL /* NUMA group */);
+    if (   !pPage
+        && g_frtSolUseKflt)
+    {
+        pPage = page_get_freelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
+                                  cbPage, 0x200 /* PG_KFLT */, NULL /* NUMA group */);
+    }
+    return pPage;
+}
+
+
+/**
+ * Retrieves a free page from the kernel cachelist.
+ *
+ * @param virtAddr      The virtual address to which this page maybe mapped in
+ *                      the future.
+ * @param cbPage        The size of the page.
+ *
+ * @return Pointer to the allocated page, NULL on failure.
+ */
+static page_t *rtR0MemObjSolPageFromCachelist(caddr_t virtAddr, size_t cbPage)
+{
+    seg_t KernelSeg;
+    KernelSeg.s_as = &kas;
+    page_t *pPage = page_get_cachelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
+                                       0 /* flags */, NULL /* NUMA group */);
+    if (   !pPage
+        && g_frtSolUseKflt)
+    {
+        pPage = page_get_cachelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
+                                   0x200 /* PG_KFLT */, NULL /* NUMA group */);
+    }
+
+    /*
+     * Remove association with the vnode for pages from the cachelist.
+     */
+    if (!PP_ISAGED(pPage))
+        page_hashout(pPage, NULL /* mutex */);
+
+    return pPage;
+}
+
+
+/**
+ * Allocates physical non-contiguous memory.
+ *
+ * @param uPhysHi   The upper physical address limit (inclusive).
+ * @param puPhys    Where to store the physical address of first page. Optional,
+ *                  can be NULL.
+ * @param cb        The size of the allocation.
+ *
+ * @return Array of allocated pages, NULL on failure.
+ */
+static page_t **rtR0MemObjSolPagesAlloc(uint64_t uPhysHi, uint64_t *puPhys, size_t cb)
+{
+    /** @todo We need to satisfy the upper physical address constraint */
+
+    /*
+     * The page freelist and cachelist both hold pages that are not mapped into any address space.
+     * The cachelist is not really free pages but when memory is exhausted they'll be moved to the
+     * free lists, it's the total of the free+cache list that we see on the 'free' column in vmstat.
+     *
+     * Reserve available memory for pages and create the pages.
+     */
+    pgcnt_t cPages = (cb + PAGESIZE - 1) >> PAGESHIFT;
+    int rc = page_resv(cPages, KM_NOSLEEP);
+    if (rc)
+    {
+        rc = page_create_wait(cPages, 0 /* flags */);
+        if (rc)
+        {
+            size_t   cbPages = cPages * sizeof(page_t *);
+            page_t **ppPages = kmem_zalloc(cbPages, KM_SLEEP);
+            if (RT_LIKELY(ppPages))
+            {
+                /*
+                 * Get pages from kseg, the 'virtAddr' here is only for colouring but unfortunately
+                 * we don't yet have the 'virtAddr' to which this memory may be mapped.
+                 */
+                caddr_t virtAddr = NULL;
+                for (size_t i = 0; i < cPages; i++, virtAddr += PAGESIZE)
+                {
+                    /*
+                     * Get a page from the freelist or cachelist.
+                     */
+                    page_t *pPage = rtR0MemObjSolPageFromFreelist(virtAddr, PAGESIZE);
+                    if (!pPage)
+                        pPage = rtR0MemObjSolPageFromCachelist(virtAddr, PAGESIZE);
+                    if (RT_UNLIKELY(!pPage))
+                    {
+                        /*
+                         * No more pages found, release was grabbed so far.
+                         */
+                        page_create_putback(cPages - i);
+                        while (--i >= 0)
+                            page_free(ppPages[i], 0 /* don't need page, move to tail of pagelist */);
+                        kmem_free(ppPages, cbPages);
+                        page_unresv(cPages);
+                        return NULL;
+                    }
+
+                    PP_CLRFREE(pPage);      /* Page is no longer free */
+                    PP_CLRAGED(pPage);      /* Page is not hashed in */
+                    ppPages[i] = pPage;
+                }
+
+                /*
+                 * We now have the pages locked exclusively, before they are mapped in
+                 * we must downgrade the lock.
+                 */
+                if (puPhys)
+                    *puPhys = (uint64_t)page_pptonum(ppPages[0]) << PAGESHIFT;
+                return ppPages;
+            }
+
+            page_create_putback(cPages);
+        }
+
+        page_unresv(cPages);
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Prepares pages allocated by rtR0MemObjSolPagesAlloc for mapping.
+ *
+ * @param    ppPages    Pointer to the page list.
+ * @param    cb         Size of the allocation.
+ * @param    auPhys     Where to store the physical address of the premapped
+ *                      pages.
+ * @param    cPages     The number of pages (entries) in @a auPhys.
+ *
+ * @returns IPRT status code.
+ */
+static int rtR0MemObjSolPagesPreMap(page_t **ppPages, size_t cb, uint64_t auPhys[], size_t cPages)
+{
+    AssertPtrReturn(ppPages, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(auPhys, VERR_INVALID_PARAMETER);
+
+    for (size_t iPage = 0; iPage < cPages; iPage++)
+    {
+        /*
+         * Prepare pages for mapping into kernel/user-space. Downgrade the
+         * exclusive page lock to a shared lock if necessary.
+         */
+        if (page_tryupgrade(ppPages[iPage]) == 1)
+            page_downgrade(ppPages[iPage]);
+
+        auPhys[iPage] = rtR0MemObjSolPageToPhys(ppPages, iPage);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Frees pages allocated by rtR0MemObjSolPagesAlloc.
+ *
+ * @param ppPages       Pointer to the page list.
+ * @param cbPages       Size of the allocation.
+ */
+static void rtR0MemObjSolPagesFree(page_t **ppPages, size_t cb)
+{
+    size_t cPages  = (cb + PAGESIZE - 1) >> PAGESHIFT;
+    size_t cbPages = cPages * sizeof(page_t *);
+    for (size_t iPage = 0; iPage < cPages; iPage++)
+    {
+        /*
+         *  We need to exclusive lock the pages before freeing them.
+         */
+        int rc = page_tryupgrade(ppPages[iPage]);
+        if (!rc)
+        {
+            page_unlock(ppPages[iPage]);
+            while (!page_lock(ppPages[iPage], SE_EXCL, NULL /* mutex */, P_RECLAIM))
+            {
+                /* nothing */;
+            }
+        }
+        page_free(ppPages[iPage], 0 /* don't need page, move to tail of pagelist */);
+    }
+    kmem_free(ppPages, cbPages);
+    page_unresv(cPages);
+}
+
+
+/**
+ * Allocates a large page to cover the required allocation size.
+ *
+ * @param puPhys        Where to store the physical address of the allocated
+ *                      page. Optional, can be NULL.
+ * @param cb            Size of the allocation.
+ *
+ * @returns Pointer to the allocated large page, NULL on failure.
+ */
+static page_t *rtR0MemObjSolLargePageAlloc(uint64_t *puPhys, size_t cb)
+{
+    /*
+     * Reserve available memory and create the sub-pages.
+     */
+    const pgcnt_t cPages = cb >> PAGESHIFT;
+    int rc = page_resv(cPages, KM_NOSLEEP);
+    if (rc)
+    {
+        rc = page_create_wait(cPages, 0 /* flags */);
+        if (rc)
+        {
+            /*
+             * Get a page off the free list. We set virtAddr to 0 since we don't know where
+             * the memory is going to be mapped.
+             */
+            seg_t KernelSeg;
+            caddr_t virtAddr  = NULL;
+            KernelSeg.s_as    = &kas;
+            page_t *pRootPage = rtR0MemObjSolPageFromFreelist(virtAddr, cb);
+            if (pRootPage)
+            {
+                AssertMsg(!(page_pptonum(pRootPage) & (cPages - 1)), ("%p:%lx cPages=%lx\n", pRootPage, page_pptonum(pRootPage), cPages));
+
+                /*
+                 * Mark all the sub-pages as non-free and not-hashed-in.
+                 * It is paramount that we destroy the list (before freeing it).
+                 */
+                page_t *pPageList = pRootPage;
+                for (size_t iPage = 0; iPage < cPages; iPage++)
+                {
+                    page_t *pPage = pPageList;
+                    AssertPtr(pPage);
+                    AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
+                        ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
+                    page_sub(&pPageList, pPage);
+
+                    /*
+                     * Ensure page is now be free and the page size-code must match that of the root page.
+                     */
+                    AssertMsg(PP_ISFREE(pPage), ("%p\n", pPage));
+                    AssertMsg(pPage->p_szc == pRootPage->p_szc, ("%p - %d expected %d \n", pPage, pPage->p_szc, pRootPage->p_szc));
+
+                    PP_CLRFREE(pPage);      /* Page no longer free */
+                    PP_CLRAGED(pPage);      /* Page no longer hashed-in */
+                }
+
+                uint64_t uPhys = (uint64_t)page_pptonum(pRootPage) << PAGESHIFT;
+                AssertMsg(!(uPhys & (cb - 1)), ("%llx %zx\n", uPhys, cb));
+                if (puPhys)
+                    *puPhys = uPhys;
+
+                return pRootPage;
+            }
+
+            page_create_putback(cPages);
+        }
+
+        page_unresv(cPages);
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Prepares the large page allocated by rtR0MemObjSolLargePageAlloc to be mapped.
+ *
+ * @param    pRootPage      Pointer to the root page.
+ * @param    cb             Size of the allocation.
+ *
+ * @returns IPRT status code.
+ */
+static int rtR0MemObjSolLargePagePreMap(page_t *pRootPage, size_t cb)
+{
+    const pgcnt_t cPages = cb >> PAGESHIFT;
+
+    Assert(page_get_pagecnt(pRootPage->p_szc) == cPages);
+    AssertMsg(!(page_pptonum(pRootPage) & (cPages - 1)), ("%p:%lx npages=%lx\n", pRootPage, page_pptonum(pRootPage), cPages));
+
+    /*
+     * We need to downgrade the sub-pages from exclusive to shared locking
+     * because otherweise we cannot <you go figure>.
+     */
+    for (pgcnt_t iPage = 0; iPage < cPages; iPage++)
+    {
+        page_t *pPage = page_nextn(pRootPage, iPage);
+        AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
+            ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
+        AssertMsg(!PP_ISFREE(pPage), ("%p\n", pPage));
+
+        if (page_tryupgrade(pPage) == 1)
+            page_downgrade(pPage);
+        AssertMsg(!PP_ISFREE(pPage), ("%p\n", pPage));
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Frees the page allocated by rtR0MemObjSolLargePageAlloc.
+ *
+ * @param    pRootPage      Pointer to the root page.
+ * @param    cb             Allocated size.
+ */
+static void rtR0MemObjSolLargePageFree(page_t *pRootPage, size_t cb)
+{
+    pgcnt_t cPages = cb >> PAGESHIFT;
+
+    Assert(page_get_pagecnt(pRootPage->p_szc) == cPages);
+    AssertMsg(!(page_pptonum(pRootPage) & (cPages - 1)), ("%p:%lx cPages=%lx\n", pRootPage, page_pptonum(pRootPage), cPages));
+
+    /*
+     * We need to exclusively lock the sub-pages before freeing the large one.
+     */
+    for (pgcnt_t iPage = 0; iPage < cPages; iPage++)
+    {
+        page_t *pPage = page_nextn(pRootPage, iPage);
+        AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
+                  ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
+        AssertMsg(!PP_ISFREE(pPage), ("%p\n", pPage));
+
+        int rc = page_tryupgrade(pPage);
+        if (!rc)
+        {
+            page_unlock(pPage);
+            while (!page_lock(pPage, SE_EXCL, NULL /* mutex */, P_RECLAIM))
+            {
+                /* nothing */;
+            }
+        }
+    }
+
+    /*
+     * Free the large page and unreserve the memory.
+     */
+    page_free_pages(pRootPage);
+    page_unresv(cPages);
+
+}
+
+
+/**
+ * Unmaps kernel/user-space mapped memory.
+ *
+ * @param    pv         Pointer to the mapped memory block.
+ * @param    cb         Size of the memory block.
+ */
+static void rtR0MemObjSolUnmap(void *pv, size_t cb)
+{
+    if (SOL_IS_KRNL_ADDR(pv))
+    {
+        hat_unload(kas.a_hat, pv, cb, HAT_UNLOAD | HAT_UNLOAD_UNLOCK);
+        vmem_free(heap_arena, pv, cb);
+    }
+    else
+    {
+        struct as *pAddrSpace = ((proc_t *)RTR0ProcHandleSelf())->p_as;
+        AssertPtr(pAddrSpace);
+        as_rangelock(pAddrSpace);
+        as_unmap(pAddrSpace, pv, cb);
+        as_rangeunlock(pAddrSpace);
+    }
+}
+
+
+/**
+ * Lock down memory mappings for a virtual address.
+ *
+ * @param    pv             Pointer to the memory to lock down.
+ * @param    cb             Size of the memory block.
+ * @param    fAccess        Page access rights (S_READ, S_WRITE, S_EXEC)
+ *
+ * @returns IPRT status code.
+ */
+static int rtR0MemObjSolLock(void *pv, size_t cb, int fPageAccess)
+{
+    /*
+     * Kernel memory mappings on x86/amd64 are always locked, only handle user-space memory.
+     */
+    if (!SOL_IS_KRNL_ADDR(pv))
+    {
+        proc_t *pProc = (proc_t *)RTR0ProcHandleSelf();
+        AssertPtr(pProc);
+        faultcode_t rc = as_fault(pProc->p_as->a_hat, pProc->p_as, (caddr_t)pv, cb, F_SOFTLOCK, fPageAccess);
+        if (rc)
+        {
+            LogRel(("rtR0MemObjSolLock failed for pv=%pv cb=%lx fPageAccess=%d rc=%d\n", pv, cb, fPageAccess, rc));
+            return VERR_LOCK_FAILED;
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Unlock memory mappings for a virtual address.
+ *
+ * @param    pv             Pointer to the locked memory.
+ * @param    cb             Size of the memory block.
+ * @param    fPageAccess    Page access rights (S_READ, S_WRITE, S_EXEC).
+ */
+static void rtR0MemObjSolUnlock(void *pv, size_t cb, int fPageAccess)
+{
+    if (!SOL_IS_KRNL_ADDR(pv))
+    {
+        proc_t *pProcess = (proc_t *)RTR0ProcHandleSelf();
+        AssertPtr(pProcess);
+        as_fault(pProcess->p_as->a_hat, pProcess->p_as, (caddr_t)pv, cb, F_SOFTUNLOCK, fPageAccess);
+    }
+}
+
+
+/**
+ * Maps a list of physical pages into user address space.
+ *
+ * @param    pVirtAddr      Where to store the virtual address of the mapping.
+ * @param    fPageAccess    Page access rights (PROT_READ, PROT_WRITE,
+ *                          PROT_EXEC)
+ * @param    paPhysAddrs    Array of physical addresses to pages.
+ * @param    cb             Size of memory being mapped.
+ *
+ * @returns IPRT status code.
+ */
+static int rtR0MemObjSolUserMap(caddr_t *pVirtAddr, unsigned fPageAccess, uint64_t *paPhysAddrs, size_t cb)
+{
+    struct as *pAddrSpace = ((proc_t *)RTR0ProcHandleSelf())->p_as;
+    int rc = VERR_INTERNAL_ERROR;
+    SEGVBOX_CRARGS Args;
+
+    Args.paPhysAddrs = paPhysAddrs;
+    Args.fPageAccess = fPageAccess;
+
+    as_rangelock(pAddrSpace);
+    map_addr(pVirtAddr, cb, 0 /* offset */, 0 /* vacalign */, MAP_SHARED);
+    if (*pVirtAddr != NULL)
+        rc = as_map(pAddrSpace, *pVirtAddr, cb, rtR0SegVBoxSolCreate, &Args);
+    else
+        rc = ENOMEM;
+    as_rangeunlock(pAddrSpace);
+
+    return RTErrConvertFromErrno(rc);
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
+{
+    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)pMem;
+
+    switch (pMemSolaris->Core.enmType)
+    {
+        case RTR0MEMOBJTYPE_LOW:
+            rtR0SolMemFree(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
+            break;
+
+        case RTR0MEMOBJTYPE_PHYS:
+            if (pMemSolaris->Core.u.Phys.fAllocated)
+            {
+                if (pMemSolaris->fLargePage)
+                    rtR0MemObjSolLargePageFree(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
+                else
+                    rtR0SolMemFree(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
+            }
+            break;
+
+        case RTR0MEMOBJTYPE_PHYS_NC:
+            rtR0MemObjSolPagesFree(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
+            break;
+
+        case RTR0MEMOBJTYPE_PAGE:
+            ddi_umem_free(pMemSolaris->Cookie);
+            break;
+
+        case RTR0MEMOBJTYPE_LOCK:
+            rtR0MemObjSolUnlock(pMemSolaris->Core.pv, pMemSolaris->Core.cb, pMemSolaris->fAccess);
+            break;
+
+        case RTR0MEMOBJTYPE_MAPPING:
+            rtR0MemObjSolUnmap(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
+            break;
+
+        case RTR0MEMOBJTYPE_RES_VIRT:
+        {
+            if (pMemSolaris->Core.u.ResVirt.R0Process == NIL_RTR0PROCESS)
+                vmem_xfree(heap_arena, pMemSolaris->Core.pv, pMemSolaris->Core.cb);
+            else
+                AssertFailed();
+            break;
+        }
+
+        case RTR0MEMOBJTYPE_CONT: /* we don't use this type here. */
+        default:
+            AssertMsgFailed(("enmType=%d\n", pMemSolaris->Core.enmType));
+            return VERR_INTERNAL_ERROR;
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
+{
+    /* Create the object. */
+    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PAGE, NULL, cb);
+    if (RT_UNLIKELY(!pMemSolaris))
+        return VERR_NO_MEMORY;
+
+    void *pvMem = ddi_umem_alloc(cb, DDI_UMEM_SLEEP, &pMemSolaris->Cookie);
+    if (RT_UNLIKELY(!pvMem))
+    {
+        rtR0MemObjDelete(&pMemSolaris->Core);
+        return VERR_NO_PAGE_MEMORY;
+    }
+
+    pMemSolaris->Core.pv  = pvMem;
+    pMemSolaris->pvHandle = NULL;
+    *ppMem = &pMemSolaris->Core;
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
+{
+    NOREF(fExecutable);
+
+    /* Create the object */
+    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOW, NULL, cb);
+    if (!pMemSolaris)
+        return VERR_NO_MEMORY;
+
+    /* Allocate physically low page-aligned memory. */
+    uint64_t uPhysHi = _4G - 1;
+    void *pvMem = rtR0SolMemAlloc(uPhysHi, NULL /* puPhys */, cb, PAGESIZE, false /* fContig */);
+    if (RT_UNLIKELY(!pvMem))
+    {
+        rtR0MemObjDelete(&pMemSolaris->Core);
+        return VERR_NO_LOW_MEMORY;
+    }
+    pMemSolaris->Core.pv = pvMem;
+    pMemSolaris->pvHandle = NULL;
+    *ppMem = &pMemSolaris->Core;
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
+{
+    NOREF(fExecutable);
+    return rtR0MemObjNativeAllocPhys(ppMem, cb, _4G - 1, PAGE_SIZE /* alignment */);
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
+{
+#if HC_ARCH_BITS == 64
+    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS_NC, NULL, cb);
+    if (RT_UNLIKELY(!pMemSolaris))
+        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;
+
+#else /* 32 bit: */
+    return VERR_NOT_SUPPORTED; /* see the RTR0MemObjAllocPhysNC specs */
+#endif
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment)
+{
+    AssertMsgReturn(PhysHighest >= 16 *_1M, ("PhysHigest=%RHp\n", PhysHighest), VERR_NOT_SUPPORTED);
+
+    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS, NULL, cb);
+    if (RT_UNLIKELY(!pMemSolaris))
+        return VERR_NO_MEMORY;
+
+    /*
+     * Allocating one large page gets special treatment.
+     */
+    static uint32_t s_cbLargePage = UINT32_MAX;
+    if (s_cbLargePage == UINT32_MAX)
+    {
+#if 0 /* currently not entirely stable, so disabled. */
+        if (page_num_pagesizes() > 1)
+            ASMAtomicWriteU32(&s_cbLargePage, page_get_pagesize(1));
+        else
+#endif
+            ASMAtomicWriteU32(&s_cbLargePage, 0);
+    }
+    uint64_t PhysAddr;
+    if (   cb == s_cbLargePage
+        && cb == uAlignment
+        && PhysHighest == NIL_RTHCPHYS)
+    {
+        /*
+         * Allocate one large page.
+         */
+        void *pvPages = rtR0MemObjSolLargePageAlloc(&PhysAddr, cb);
+        if (RT_LIKELY(pvPages))
+        {
+            AssertMsg(!(PhysAddr & (cb - 1)), ("%RHp\n", PhysAddr));
+            pMemSolaris->Core.pv                = NULL;
+            pMemSolaris->Core.u.Phys.PhysBase   = PhysAddr;
+            pMemSolaris->Core.u.Phys.fAllocated = true;
+            pMemSolaris->pvHandle               = pvPages;
+            pMemSolaris->fLargePage             = true;
+
+            *ppMem = &pMemSolaris->Core;
+            return VINF_SUCCESS;
+        }
+    }
+    else
+    {
+        /*
+         * Allocate physically contiguous memory aligned as specified.
+         */
+        AssertCompile(NIL_RTHCPHYS == UINT64_MAX);
+        PhysAddr = PhysHighest;
+        void *pvMem = rtR0SolMemAlloc(PhysHighest, &PhysAddr, cb, uAlignment, true /* fContig */);
+        if (RT_LIKELY(pvMem))
+        {
+            Assert(!(PhysAddr & PAGE_OFFSET_MASK));
+            Assert(PhysAddr < PhysHighest);
+            Assert(PhysAddr + cb <= PhysHighest);
+
+            pMemSolaris->Core.pv                = pvMem;
+            pMemSolaris->Core.u.Phys.PhysBase   = PhysAddr;
+            pMemSolaris->Core.u.Phys.fAllocated = true;
+            pMemSolaris->pvHandle               = NULL;
+            pMemSolaris->fLargePage             = false;
+
+            *ppMem = &pMemSolaris->Core;
+            return VINF_SUCCESS;
+        }
+    }
+    rtR0MemObjDelete(&pMemSolaris->Core);
+    return VERR_NO_CONT_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy)
+{
+    AssertReturn(uCachePolicy == RTMEM_CACHE_POLICY_DONT_CARE, VERR_NOT_SUPPORTED);
+
+    /* Create the object. */
+    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS, NULL, cb);
+    if (!pMemSolaris)
+        return VERR_NO_MEMORY;
+
+    /* There is no allocation here, it needs to be mapped somewhere first. */
+    pMemSolaris->Core.u.Phys.fAllocated   = false;
+    pMemSolaris->Core.u.Phys.PhysBase     = Phys;
+    pMemSolaris->Core.u.Phys.uCachePolicy = uCachePolicy;
+    *ppMem = &pMemSolaris->Core;
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess,
+                                         RTR0PROCESS R0Process)
+{
+    AssertReturn(R0Process == RTR0ProcHandleSelf(), VERR_INVALID_PARAMETER);
+    NOREF(fAccess);
+
+    /* Create the locking object */
+    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb);
+    if (!pMemSolaris)
+        return VERR_NO_MEMORY;
+
+    /* Lock down user pages. */
+    int fPageAccess = S_READ;
+    if (fAccess & RTMEM_PROT_WRITE)
+        fPageAccess = S_WRITE;
+    if (fAccess & RTMEM_PROT_EXEC)
+        fPageAccess = S_EXEC;
+    int rc = rtR0MemObjSolLock((void *)R3Ptr, cb, fPageAccess);
+    if (RT_FAILURE(rc))
+    {
+        LogRel(("rtR0MemObjNativeLockUser: rtR0MemObjSolLock failed rc=%d\n", rc));
+        rtR0MemObjDelete(&pMemSolaris->Core);
+        return rc;
+    }
+
+    /* Fill in the object attributes and return successfully. */
+    pMemSolaris->Core.u.Lock.R0Process  = R0Process;
+    pMemSolaris->pvHandle               = NULL;
+    pMemSolaris->fAccess                = fPageAccess;
+    *ppMem = &pMemSolaris->Core;
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
+{
+    NOREF(fAccess);
+
+    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, pv, cb);
+    if (!pMemSolaris)
+        return VERR_NO_MEMORY;
+
+    /* Lock down kernel pages. */
+    int fPageAccess = S_READ;
+    if (fAccess & RTMEM_PROT_WRITE)
+        fPageAccess = S_WRITE;
+    if (fAccess & RTMEM_PROT_EXEC)
+        fPageAccess = S_EXEC;
+    int rc = rtR0MemObjSolLock(pv, cb, fPageAccess);
+    if (RT_FAILURE(rc))
+    {
+        LogRel(("rtR0MemObjNativeLockKernel: rtR0MemObjSolLock failed rc=%d\n", rc));
+        rtR0MemObjDelete(&pMemSolaris->Core);
+        return rc;
+    }
+
+    /* Fill in the object attributes and return successfully. */
+    pMemSolaris->Core.u.Lock.R0Process = NIL_RTR0PROCESS;
+    pMemSolaris->pvHandle              = NULL;
+    pMemSolaris->fAccess               = fPageAccess;
+    *ppMem = &pMemSolaris->Core;
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
+{
+    PRTR0MEMOBJSOL  pMemSolaris;
+
+    /*
+     * Use xalloc.
+     */
+    void *pv = vmem_xalloc(heap_arena, cb, uAlignment, 0 /* phase */, 0 /* nocross */,
+                           NULL /* minaddr */, NULL /* maxaddr */, VM_SLEEP);
+    if (RT_UNLIKELY(!pv))
+        return VERR_NO_MEMORY;
+
+    /* Create the object. */
+    pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_RES_VIRT, pv, cb);
+    if (!pMemSolaris)
+    {
+        LogRel(("rtR0MemObjNativeReserveKernel failed to alloc memory object.\n"));
+        vmem_xfree(heap_arena, pv, cb);
+        return VERR_NO_MEMORY;
+    }
+
+    pMemSolaris->Core.u.ResVirt.R0Process = NIL_RTR0PROCESS;
+    *ppMem = &pMemSolaris->Core;
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
+{
+    return VERR_NOT_SUPPORTED;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
+                                          unsigned fProt, size_t offSub, size_t cbSub)
+{
+    /** @todo rtR0MemObjNativeMapKernel / Solaris - Should be fairly simple alloc kernel memory and memload it. */
+    return VERR_NOT_SUPPORTED;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, PRTR0MEMOBJINTERNAL pMemToMap, RTR3PTR R3PtrFixed,
+                                        size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
+{
+    /*
+     * Fend off things we cannot do.
+     */
+    AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED);
+    AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
+    if (uAlignment != PAGE_SIZE)
+        return VERR_NOT_SUPPORTED;
+
+    /*
+     * Get parameters from the source object.
+     */
+    PRTR0MEMOBJSOL  pMemToMapSolaris     = (PRTR0MEMOBJSOL)pMemToMap;
+    void           *pv                   = pMemToMapSolaris->Core.pv;
+    size_t          cb                   = pMemToMapSolaris->Core.cb;
+    size_t          cPages               = cb >> PAGE_SHIFT;
+
+    /*
+     * Create the mapping object
+     */
+    PRTR0MEMOBJSOL pMemSolaris;
+    pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, cb);
+    if (RT_UNLIKELY(!pMemSolaris))
+        return VERR_NO_MEMORY;
+
+    int rc = VINF_SUCCESS;
+    uint64_t *paPhysAddrs = kmem_zalloc(sizeof(uint64_t) * cPages, KM_SLEEP);
+    if (RT_LIKELY(paPhysAddrs))
+    {
+        /*
+         * Prepare the pages according to type.
+         */
+        if (pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS_NC)
+            rc = rtR0MemObjSolPagesPreMap(pMemToMapSolaris->pvHandle, cb, paPhysAddrs, cPages);
+        else if (   pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS
+                 && pMemToMapSolaris->fLargePage)
+        {
+            RTHCPHYS Phys = pMemToMapSolaris->Core.u.Phys.PhysBase;
+            for (pgcnt_t iPage = 0; iPage < cPages; iPage++, Phys += PAGE_SIZE)
+                paPhysAddrs[iPage] = Phys;
+            rc = rtR0MemObjSolLargePagePreMap(pMemToMapSolaris->pvHandle, cb);
+        }
+        else
+        {
+            /*
+             * Have kernel mapping, just translate virtual to physical.
+             */
+            AssertPtr(pv);
+            rc = VINF_SUCCESS;
+            for (size_t iPage = 0; iPage < cPages; iPage++)
+            {
+                paPhysAddrs[iPage] = rtR0MemObjSolVirtToPhys(pv);
+                if (RT_UNLIKELY(paPhysAddrs[iPage] == -(uint64_t)1))
+                {
+                    LogRel(("rtR0MemObjNativeMapUser: no page to map.\n"));
+                    rc = VERR_MAP_FAILED;
+                    break;
+                }
+                pv = (void *)((uintptr_t)pv + PAGE_SIZE);
+            }
+        }
+        if (RT_SUCCESS(rc))
+        {
+            unsigned fPageAccess = PROT_READ;
+            if (fProt & RTMEM_PROT_WRITE)
+                fPageAccess |= PROT_WRITE;
+            if (fProt & RTMEM_PROT_EXEC)
+                fPageAccess |= PROT_EXEC;
+
+            /*
+             * Perform the actual mapping.
+             */
+            caddr_t UserAddr = NULL;
+            rc = rtR0MemObjSolUserMap(&UserAddr, fPageAccess, paPhysAddrs, cb);
+            if (RT_SUCCESS(rc))
+            {
+                pMemSolaris->Core.u.Mapping.R0Process = R0Process;
+                pMemSolaris->Core.pv                  = UserAddr;
+
+                *ppMem = &pMemSolaris->Core;
+                kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
+                return VINF_SUCCESS;
+            }
+
+            LogRel(("rtR0MemObjNativeMapUser: rtR0MemObjSolUserMap failed rc=%d.\n", rc));
+        }
+
+        rc = VERR_MAP_FAILED;
+        kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+    rtR0MemObjDelete(&pMemSolaris->Core);
+    return rc;
+}
+
+
+DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
+{
+    NOREF(pMem);
+    NOREF(offSub);
+    NOREF(cbSub);
+    NOREF(fProt);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+DECLHIDDEN(RTHCPHYS) rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
+{
+    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)pMem;
+
+    switch (pMemSolaris->Core.enmType)
+    {
+        case RTR0MEMOBJTYPE_PHYS_NC:
+            if (pMemSolaris->Core.u.Phys.fAllocated)
+            {
+                uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
+                return rtR0MemObjSolVirtToPhys(pb);
+            }
+            return rtR0MemObjSolPageToPhys(pMemSolaris->pvHandle, iPage);
+
+        case RTR0MEMOBJTYPE_PAGE:
+        case RTR0MEMOBJTYPE_LOW:
+        case RTR0MEMOBJTYPE_LOCK:
+        {
+            uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
+            return rtR0MemObjSolVirtToPhys(pb);
+        }
+
+        /*
+         * Although mapping can be handled by rtR0MemObjSolVirtToPhys(offset) like the above case,
+         * request it from the parent so that we have a clear distinction between CONT/PHYS_NC.
+         */
+        case RTR0MEMOBJTYPE_MAPPING:
+            return rtR0MemObjNativeGetPagePhysAddr(pMemSolaris->Core.uRel.Child.pParent, iPage);
+
+        case RTR0MEMOBJTYPE_CONT:
+        case RTR0MEMOBJTYPE_PHYS:
+            AssertFailed(); /* handled by the caller */
+        case RTR0MEMOBJTYPE_RES_VIRT:
+        default:
+            return NIL_RTHCPHYS;
+    }
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.h
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.h	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.h	(revision 40968)
@@ -0,0 +1,296 @@
+/* $Id$ */
+/** @file
+ * IPRT - Ring-0 Memory Objects - Segment driver, Solaris.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+#ifndef ___r0drv_solaris_memobj_r0drv_solaris_h
+#define ___r0drv_solaris_memobj_r0drv_solaris_h
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+typedef struct SEGVBOX_CRARGS
+{
+    uint64_t *paPhysAddrs;
+    uint_t    fPageAccess;
+} SEGVBOX_CRARGS;
+typedef SEGVBOX_CRARGS *PSEGVBOX_CRARGS;
+
+typedef struct SEGVBOX_DATA
+{
+    uint_t    fPageAccess;
+} SEGVBOX_DATA;
+typedef SEGVBOX_DATA *PSEGVBOX_DATA;
+
+static struct seg_ops s_SegVBoxOps;
+static vnode_t s_segVBoxVnode;
+
+
+DECLINLINE(int) rtR0SegVBoxSolCreate(seg_t *pSeg, void *pvArgs)
+{
+    struct as      *pAddrSpace = pSeg->s_as;
+    PSEGVBOX_CRARGS pArgs      = pvArgs;
+    PSEGVBOX_DATA   pData      = kmem_zalloc(sizeof(*pData), KM_SLEEP);
+
+    AssertPtr(pAddrSpace);
+    AssertPtr(pArgs);
+    AssertPtr(pData);
+
+    hat_map(pAddrSpace->a_hat, pSeg->s_base, pSeg->s_size, HAT_MAP);
+    pData->fPageAccess = pArgs->fPageAccess | PROT_USER;
+
+    pSeg->s_ops  = &s_SegVBoxOps;
+    pSeg->s_data = pData;
+
+    /*
+     * Now load the locked mappings to the pages.
+     */
+    caddr_t virtAddr = pSeg->s_base;
+    pgcnt_t cPages   = (pSeg->s_size + PAGESIZE - 1) >> PAGESHIFT;
+    for (pgcnt_t iPage = 0; iPage < cPages; ++iPage, virtAddr += PAGESIZE)
+    {
+        hat_devload(pAddrSpace->a_hat, virtAddr, PAGESIZE, pArgs->paPhysAddrs[iPage] >> PAGESHIFT,
+                    pData->fPageAccess | HAT_UNORDERED_OK, HAT_LOAD | HAT_LOAD_LOCK);
+    }
+
+    return 0;
+}
+
+
+static int rtR0SegVBoxSolDup(seg_t *pSrcSeg, seg_t *pDstSeg)
+{
+    /*
+     * Duplicate a segment and return the new segment in 'pDstSeg'.
+     */
+    PSEGVBOX_DATA pSrcData = pSrcSeg->s_data;
+    PSEGVBOX_DATA pDstData = kmem_zalloc(sizeof(*pDstData), KM_SLEEP);
+
+    AssertPtr(pDstData);
+    AssertPtr(pSrcData);
+
+    pDstData->fPageAccess  = pSrcData->fPageAccess;
+    pDstSeg->s_ops         = &s_SegVBoxOps;
+    pDstSeg->s_data        = pDstData;
+
+    return 0;
+}
+
+
+static int rtR0SegVBoxSolUnmap(seg_t *pSeg, caddr_t virtAddr, size_t cb)
+{
+    /** @todo make these into release assertions. */
+    if (   virtAddr < pSeg->s_base
+        || virtAddr + cb > pSeg->s_base + pSeg->s_size
+        || (cb & PAGEOFFSET) || ((uintptr_t)virtAddr & PAGEOFFSET))
+    {
+        panic("rtRt0SegVBoxSolUnmap");
+    }
+
+    if (virtAddr != pSeg->s_base || cb != pSeg->s_size)
+        return ENOTSUP;
+
+    hat_unload(pSeg->s_as->a_hat, virtAddr, cb, HAT_UNLOAD_UNMAP | HAT_UNLOAD_UNLOCK);
+
+    seg_free(pSeg);
+    return 0;
+}
+
+
+static void rtR0SegVBoxSolFree(seg_t *pSeg)
+{
+    PSEGVBOX_DATA pData = pSeg->s_data;
+    kmem_free(pData, sizeof(*pData));
+}
+
+
+static int rtR0SegVBoxSolFault(struct hat *pHat, seg_t *pSeg, caddr_t virtAddr, size_t cb, enum fault_type FaultType,
+                               enum seg_rw ReadWrite)
+{
+    /*
+     * We would demand fault if the (u)read() path would SEGOP_FAULT() on buffers mapped in via our
+     * segment driver i.e. prefaults before DMA. Don't fail in such case where we're called directly,
+     * see #5047.
+     */
+    return 0;
+}
+
+
+static int rtR0SegVBoxSolFaultA(seg_t *pSeg, caddr_t virtAddr)
+{
+    return 0;
+}
+
+
+static int rtR0SegVBoxSolSetProt(seg_t *pSeg, caddr_t virtAddr, size_t cb, uint_t fPageAccess)
+{
+    return EACCES;
+}
+
+
+static int rtR0SegVBoxSolCheckProt(seg_t *pSeg, caddr_t virtAddr, size_t cb, uint_t fPageAccess)
+{
+    return EINVAL;
+}
+
+
+static int rtR0SegVBoxSolKluster(seg_t *pSeg, caddr_t virtAddr, ssize_t Delta)
+{
+    return -1;
+}
+
+
+static int rtR0SegVBoxSolSync(seg_t *pSeg, caddr_t virtAddr, size_t cb, int Attr, uint_t fFlags)
+{
+    return 0;
+}
+
+
+static size_t rtR0SegVBoxSolInCore(seg_t *pSeg, caddr_t virtAddr, size_t cb, char *pVec)
+{
+    size_t cbLen = (cb + PAGEOFFSET) & PAGEMASK;
+    for (virtAddr = 0; cbLen != 0; cbLen -= PAGESIZE, virtAddr += PAGESIZE)
+        *pVec++ = 1;
+    return cbLen;
+}
+
+
+static int rtR0SegVBoxSolLockOp(seg_t *pSeg, caddr_t virtAddr, size_t cb, int Attr, int Op, ulong_t *pLockMap, size_t off)
+{
+    return 0;
+}
+
+
+static int rtR0SegVBoxSolGetProt(seg_t *pSeg, caddr_t virtAddr, size_t cb, uint_t *pafPageAccess)
+{
+    PSEGVBOX_DATA pData = pSeg->s_data;
+    size_t iPage = seg_page(pSeg, virtAddr + cb) - seg_page(pSeg, virtAddr) + 1;
+    if (iPage)
+    {
+        do
+        {
+            iPage--;
+            pafPageAccess[iPage] = pData->fPageAccess;
+        } while (iPage);
+    }
+    return 0;
+}
+
+
+static u_offset_t rtR0SegVBoxSolGetOffset(seg_t *pSeg, caddr_t virtAddr)
+{
+    return ((uintptr_t)virtAddr - (uintptr_t)pSeg->s_base);
+}
+
+
+static int rtR0SegVBoxSolGetType(seg_t *pSeg, caddr_t virtAddr)
+{
+    return MAP_SHARED;
+}
+
+
+static int rtR0SegVBoxSolGetVp(seg_t *pSeg, caddr_t virtAddr, vnode_t **ppVnode)
+{
+    *ppVnode = &s_segVBoxVnode;
+    return 0;
+}
+
+
+static int rtR0SegVBoxSolAdvise(seg_t *pSeg, caddr_t virtAddr, size_t cb, uint_t Behav /* wut? */)
+{
+    return 0;
+}
+
+
+static void rtR0SegVBoxSolDump(seg_t *pSeg)
+{
+    /* Nothing to do. */
+}
+
+
+static int rtR0SegVBoxSolPageLock(seg_t *pSeg, caddr_t virtAddr, size_t cb, page_t ***pppPage, enum lock_type LockType, enum seg_rw ReadWrite)
+{
+    return ENOTSUP;
+}
+
+
+static int rtR0SegVBoxSolSetPageSize(seg_t *pSeg, caddr_t virtAddr, size_t cb, uint_t SizeCode)
+{
+    return ENOTSUP;
+}
+
+
+static int rtR0SegVBoxSolGetMemId(seg_t *pSeg, caddr_t virtAddr, memid_t *pMemId)
+{
+    return ENODEV;
+}
+
+
+static lgrp_mem_policy_info_t *rtR0SegVBoxSolGetPolicy(seg_t *pSeg, caddr_t virtAddr)
+{
+    return NULL;
+}
+
+
+static int rtR0SegVBoxSolCapable(seg_t *pSeg, segcapability_t Capab)
+{
+    return 0;
+}
+
+
+static struct seg_ops s_SegVBoxOps =
+{
+    rtR0SegVBoxSolDup,
+    rtR0SegVBoxSolUnmap,
+    rtR0SegVBoxSolFree,
+    rtR0SegVBoxSolFault,
+    rtR0SegVBoxSolFaultA,
+    rtR0SegVBoxSolSetProt,
+    rtR0SegVBoxSolCheckProt,
+    rtR0SegVBoxSolKluster,
+    NULL,                       /* swapout */
+    rtR0SegVBoxSolSync,
+    rtR0SegVBoxSolInCore,
+    rtR0SegVBoxSolLockOp,
+    rtR0SegVBoxSolGetProt,
+    rtR0SegVBoxSolGetOffset,
+    rtR0SegVBoxSolGetType,
+    rtR0SegVBoxSolGetVp,
+    rtR0SegVBoxSolAdvise,
+    rtR0SegVBoxSolDump,
+    rtR0SegVBoxSolPageLock,
+    rtR0SegVBoxSolSetPageSize,
+    rtR0SegVBoxSolGetMemId,
+    rtR0SegVBoxSolGetPolicy,
+    rtR0SegVBoxSolCapable
+};
+
+#endif /* ___r0drv_solaris_memobj_r0drv_solaris_h */
+
Index: /trunk/src/VBox/Runtime/r0drv/solaris/mp-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/mp-r0drv-solaris.c	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/mp-r0drv-solaris.c	(revision 40968)
@@ -0,0 +1,346 @@
+/* $Id$ */
+/** @file
+ * IPRT - Multiprocessor, Ring-0 Driver, Solaris.
+ */
+
+/*
+ * Copyright (C) 2008 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/mp.h>
+#include <iprt/cpuset.h>
+#include <iprt/thread.h>
+
+#include <iprt/asm.h>
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/err.h>
+#include "r0drv/mp-r0drv.h"
+
+typedef int FNRTMPSOLWORKER(void *pvUser1, void *pvUser2, void *pvUser3);
+typedef FNRTMPSOLWORKER *PFNRTMPSOLWORKER;
+
+
+RTDECL(bool) RTMpIsCpuWorkPending(void)
+{
+    return false;
+}
+
+
+RTDECL(RTCPUID) RTMpCpuId(void)
+{
+    return CPU->cpu_id;
+}
+
+
+RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
+{
+    return idCpu < RTCPUSET_MAX_CPUS && idCpu <= max_cpuid ? idCpu : -1;
+}
+
+
+RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
+{
+    return (unsigned)iCpu <= max_cpuid ? iCpu : NIL_RTCPUID;
+}
+
+
+RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
+{
+    return max_cpuid;
+}
+
+
+RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
+{
+    /*
+     * We cannot query CPU status recursively, check cpu member from cached set.
+     */
+    if (idCpu >= ncpus)
+        return false;
+
+    return RTCpuSetIsMember(&g_rtMpSolCpuSet, idCpu);
+}
+
+
+RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
+{
+    return idCpu < ncpus;
+}
+
+
+RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
+{
+    RTCPUID idCpu;
+
+    RTCpuSetEmpty(pSet);
+    idCpu = RTMpGetMaxCpuId(); /* it's inclusive */
+    do
+    {
+        if (RTMpIsCpuPossible(idCpu))
+            RTCpuSetAdd(pSet, idCpu);
+    } while (idCpu-- > 0);
+
+    return pSet;
+}
+
+
+RTDECL(RTCPUID) RTMpGetCount(void)
+{
+    return ncpus;
+}
+
+
+RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
+{
+    /*
+     * We cannot query CPU status recursively, return the cached set.
+     */
+    *pSet = g_rtMpSolCpuSet;
+    return pSet;
+}
+
+
+RTDECL(RTCPUID) RTMpGetOnlineCount(void)
+{
+    RTCPUSET Set;
+    RTMpGetOnlineSet(&Set);
+    return RTCpuSetCount(&Set);
+}
+
+
+/**
+ * Wrapper to Solaris IPI infrastructure.
+ *
+ * @param    pCpuSet        Pointer to Solaris CPU set.
+ * @param    pfnSolWorker     Function to execute on target CPU(s).
+ * @param     pArgs            Pointer to RTMPARGS to pass to @a pfnSolWorker.
+ *
+ * @returns Solaris error code.
+ */
+static void rtMpSolCrossCall(PRTSOLCPUSET pCpuSet, PFNRTMPSOLWORKER pfnSolWorker, PRTMPARGS pArgs)
+{
+    AssertPtrReturnVoid(pCpuSet);
+    AssertPtrReturnVoid(pfnSolWorker);
+    AssertPtrReturnVoid(pCpuSet);
+
+    if (g_frtSolOldIPI)
+    {
+        if (g_frtSolOldIPIUlong)
+        {
+            g_rtSolXcCall.u.pfnSol_xc_call_old_ulong((xc_arg_t)pArgs,          /* Arg to IPI function */
+                                                     0,                        /* Arg2, ignored */
+                                                     0,                        /* Arg3, ignored */
+                                                     IPRT_SOL_X_CALL_HIPRI,    /* IPI priority */
+                                                     pCpuSet->auCpus[0],       /* Target CPU(s) */
+                                                     (xc_func_t)pfnSolWorker); /* Function to execute on target(s) */
+        }
+        else
+        {
+            g_rtSolXcCall.u.pfnSol_xc_call_old((xc_arg_t)pArgs,          /* Arg to IPI function */
+                                               0,                        /* Arg2, ignored */
+                                               0,                        /* Arg3, ignored */
+                                               IPRT_SOL_X_CALL_HIPRI,    /* IPI priority */
+                                               *pCpuSet,                 /* Target CPU set */
+                                               (xc_func_t)pfnSolWorker); /* Function to execute on target(s) */
+        }
+    }
+    else
+    {
+        g_rtSolXcCall.u.pfnSol_xc_call((xc_arg_t)pArgs,          /* Arg to IPI function */
+                                       0,                        /* Arg2 */
+                                       0,                        /* Arg3 */
+                                       &pCpuSet->auCpus[0],      /* Target CPU set */
+                                       (xc_func_t)pfnSolWorker); /* Function to execute on target(s) */
+    }
+}
+
+
+/**
+ * Wrapper between the native solaris per-cpu callback and PFNRTWORKER
+ * for the RTMpOnAll API.
+ *
+ * @param   uArgs       Pointer to the RTMPARGS package.
+ * @param   uIgnored1   Ignored.
+ * @param   uIgnored2   Ignored.
+ */
+static int rtMpSolOnAllCpuWrapper(void *uArg, void *uIgnored1, void *uIgnored2)
+{
+    PRTMPARGS pArgs = (PRTMPARGS)(uArg);
+
+    /*
+     * Solaris CPU cross calls execute on offline CPUs too. Check our CPU cache
+     * set and ignore if it's offline.
+     */
+    if (!RTMpIsCpuOnline(RTMpCpuId()))
+        return 0;
+
+    pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2);
+
+    NOREF(uIgnored1);
+    NOREF(uIgnored2);
+    return 0;
+}
+
+
+RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
+{
+    RTMPARGS Args;
+    RT_ASSERT_INTS_ON();
+
+    Args.pfnWorker = pfnWorker;
+    Args.pvUser1 = pvUser1;
+    Args.pvUser2 = pvUser2;
+    Args.idCpu = NIL_RTCPUID;
+    Args.cHits = 0;
+
+    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+    RTThreadPreemptDisable(&PreemptState);
+
+    RTSOLCPUSET CpuSet;
+    for (int i = 0; i < IPRT_SOL_SET_WORDS; i++)
+        CpuSet.auCpus[i] = (ulong_t)-1L;
+
+    rtMpSolCrossCall(&CpuSet, rtMpSolOnAllCpuWrapper, &Args);
+
+    RTThreadPreemptRestore(&PreemptState);
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Wrapper between the native solaris per-cpu callback and PFNRTWORKER
+ * for the RTMpOnOthers API.
+ *
+ * @param   uArgs       Pointer to the RTMPARGS package.
+ * @param   uIgnored1   Ignored.
+ * @param   uIgnored2   Ignored.
+ */
+static int rtMpSolOnOtherCpusWrapper(void *uArg, void *uIgnored1, void *uIgnored2)
+{
+    PRTMPARGS pArgs = (PRTMPARGS)(uArg);
+    RTCPUID idCpu = RTMpCpuId();
+
+    Assert(idCpu != pArgs->idCpu);
+    pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
+
+    NOREF(uIgnored1);
+    NOREF(uIgnored2);
+    return 0;
+}
+
+
+RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
+{
+    RTMPARGS Args;
+    RT_ASSERT_INTS_ON();
+
+    Args.pfnWorker = pfnWorker;
+    Args.pvUser1 = pvUser1;
+    Args.pvUser2 = pvUser2;
+    Args.idCpu = RTMpCpuId();
+    Args.cHits = 0;
+
+    /* The caller is supposed to have disabled preemption, but take no chances. */
+    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+    RTThreadPreemptDisable(&PreemptState);
+
+    RTSOLCPUSET CpuSet;
+    for (int i = 0; i < IPRT_SOL_SET_WORDS; i++)
+        CpuSet.auCpus[0] = (ulong_t)-1L;
+    BT_CLEAR(CpuSet.auCpus, RTMpCpuId());
+
+    rtMpSolCrossCall(&CpuSet, rtMpSolOnOtherCpusWrapper, &Args);
+
+    RTThreadPreemptRestore(&PreemptState);
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Wrapper between the native solaris per-cpu callback and PFNRTWORKER
+ * for the RTMpOnSpecific API.
+ *
+ * @param   uArgs       Pointer to the RTMPARGS package.
+ * @param   uIgnored1   Ignored.
+ * @param   uIgnored2   Ignored.
+ *
+ * @returns Solaris error code.
+ */
+static int rtMpSolOnSpecificCpuWrapper(void *uArg, void *uIgnored1, void *uIgnored2)
+{
+    PRTMPARGS pArgs = (PRTMPARGS)(uArg);
+    RTCPUID idCpu = RTMpCpuId();
+
+    Assert(idCpu == pArgs->idCpu);
+    pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
+    ASMAtomicIncU32(&pArgs->cHits);
+
+    NOREF(uIgnored1);
+    NOREF(uIgnored2);
+    return 0;
+}
+
+
+RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
+{
+    RTMPARGS Args;
+    RT_ASSERT_INTS_ON();
+
+    if (idCpu >= ncpus)
+        return VERR_CPU_NOT_FOUND;
+
+    if (RT_UNLIKELY(!RTMpIsCpuOnline(idCpu)))
+        return RTMpIsCpuPresent(idCpu) ? VERR_CPU_OFFLINE : VERR_CPU_NOT_FOUND;
+
+    Args.pfnWorker = pfnWorker;
+    Args.pvUser1 = pvUser1;
+    Args.pvUser2 = pvUser2;
+    Args.idCpu = idCpu;
+    Args.cHits = 0;
+
+    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+    RTThreadPreemptDisable(&PreemptState);
+
+    RTSOLCPUSET CpuSet;
+    for (int i = 0; i < IPRT_SOL_SET_WORDS; i++)
+        CpuSet.auCpus[i] = 0;
+    BT_SET(CpuSet.auCpus, idCpu);
+
+    rtMpSolCrossCall(&CpuSet, rtMpSolOnSpecificCpuWrapper, &Args);
+
+    RTThreadPreemptRestore(&PreemptState);
+
+    Assert(ASMAtomicUoReadU32(&Args.cHits) <= 1);
+
+    return ASMAtomicUoReadU32(&Args.cHits) == 1
+         ? VINF_SUCCESS
+         : VERR_CPU_NOT_FOUND;
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/solaris/mpnotification-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/mpnotification-r0drv-solaris.c	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/mpnotification-r0drv-solaris.c	(revision 40968)
@@ -0,0 +1,187 @@
+/* $Id$ */
+/** @file
+ * IPRT - Multiprocessor Event Notifications, Ring-0 Driver, Solaris.
+ */
+
+/*
+ * Copyright (C) 2008 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+
+#include <iprt/err.h>
+#include <iprt/mp.h>
+#include <iprt/cpuset.h>
+#include <iprt/string.h>
+#include <iprt/thread.h>
+#include "r0drv/mp-r0drv.h"
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Whether CPUs are being watched or not. */
+static volatile bool g_fSolCpuWatch = false;
+/** Set of online cpus that is maintained by the MP callback.
+ * This avoids locking issues querying the set from the kernel as well as
+ * eliminating any uncertainty regarding the online status during the
+ * callback. */
+RTCPUSET g_rtMpSolCpuSet;
+
+/**
+ * Internal solaris representation for watching CPUs.
+ */
+typedef struct RTMPSOLWATCHCPUS
+{
+    /** Function pointer to Mp worker. */
+    PFNRTMPWORKER   pfnWorker;
+    /** Argument to pass to the Mp worker. */
+    void           *pvArg;
+} RTMPSOLWATCHCPUS;
+typedef RTMPSOLWATCHCPUS *PRTMPSOLWATCHCPUS;
+
+
+/**
+ * PFNRTMPWORKER worker for executing Mp events on the target CPU.
+ *
+ * @param    idCpu          The current CPU Id.
+ * @param    pvArg          Opaque pointer to event type (online/offline).
+ * @param    pvIgnored1     Ignored.
+ */
+static void rtMpNotificationSolOnCurrentCpu(RTCPUID idCpu, void *pvArg, void *pvIgnored1)
+{
+    NOREF(pvIgnored1);
+    NOREF(idCpu);
+
+    PRTMPARGS pArgs = (PRTMPARGS)pvArg;
+    AssertRelease(pArgs && pArgs->idCpu == RTMpCpuId());
+    Assert(pArgs->pvUser1);
+    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
+
+    RTMPEVENT enmMpEvent = *(RTMPEVENT *)pArgs->pvUser1;
+    rtMpNotificationDoCallbacks(enmMpEvent, pArgs->idCpu);
+}
+
+
+/**
+ * Solaris callback function for Mp event notification.
+ *
+ * @param    CpuState   The current event/state of the CPU.
+ * @param    iCpu       Which CPU is this event fore.
+ * @param    pvArg      Ignored.
+ *
+ * @remarks This function assumes index == RTCPUID.
+ * @returns Solaris error code.
+ */
+static int rtMpNotificationCpuEvent(cpu_setup_t CpuState, int iCpu, void *pvArg)
+{
+    RTMPEVENT enmMpEvent;
+
+    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+    RTThreadPreemptDisable(&PreemptState);
+
+    /*
+     * Update our CPU set structures first regardless of whether we've been
+     * scheduled on the right CPU or not, this is just atomic accounting.
+     */
+    if (CpuState == CPU_ON)
+    {
+        enmMpEvent = RTMPEVENT_ONLINE;
+        RTCpuSetAdd(&g_rtMpSolCpuSet, iCpu);
+    }
+    else if (CpuState == CPU_OFF)
+    {
+        enmMpEvent = RTMPEVENT_OFFLINE;
+        RTCpuSetDel(&g_rtMpSolCpuSet, iCpu);
+    }
+    else
+        return 0;
+
+    /*
+     * Since we don't absolutely need to do CPU bound code in any of the CPU offline
+     * notification hooks, run it on the current CPU. Scheduling a callback to execute
+     * on the CPU going offline at this point is too late and will not work reliably.
+     */
+    bool fRunningOnTargetCpu = iCpu == RTMpCpuId();
+    if (   fRunningOnTargetCpu == true
+        || enmMpEvent == RTMPEVENT_OFFLINE)
+    {
+        rtMpNotificationDoCallbacks(enmMpEvent, iCpu);
+    }
+    else
+    {
+        /*
+         * We're not on the target CPU, schedule (synchronous) the event notification callback
+         * to run on the target CPU i.e. the CPU that was online'd.
+         */
+        RTMPARGS Args;
+        RT_ZERO(Args);
+        Args.pvUser1 = &enmMpEvent;
+        Args.pvUser2 = NULL;
+        Args.idCpu   = iCpu;
+        RTMpOnSpecific(iCpu, rtMpNotificationSolOnCurrentCpu, &Args, NULL /* pvIgnored1 */);
+    }
+
+    RTThreadPreemptRestore(&PreemptState);
+
+    NOREF(pvArg);
+    return 0;
+}
+
+
+DECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
+{
+    if (ASMAtomicReadBool(&g_fSolCpuWatch) == true)
+        return VERR_WRONG_ORDER;
+
+    /*
+     * Register the callback building the online cpu set as we do so.
+     */
+    RTCpuSetEmpty(&g_rtMpSolCpuSet);
+
+    mutex_enter(&cpu_lock);
+    register_cpu_setup_func(rtMpNotificationCpuEvent, NULL /* pvArg */);
+
+    for (int i = 0; i < (int)RTMpGetCount(); ++i)
+        if (cpu_is_online(cpu[i]))
+            rtMpNotificationCpuEvent(CPU_ON, i, NULL /* pvArg */);
+
+    ASMAtomicWriteBool(&g_fSolCpuWatch, true);
+    mutex_exit(&cpu_lock);
+
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
+{
+    if (ASMAtomicReadBool(&g_fSolCpuWatch) == true)
+    {
+        mutex_enter(&cpu_lock);
+        unregister_cpu_setup_func(rtMpNotificationCpuEvent, NULL /* pvArg */);
+        ASMAtomicWriteBool(&g_fSolCpuWatch, false);
+        mutex_exit(&cpu_lock);
+    }
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/solaris/process-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/process-r0drv-solaris.c	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/process-r0drv-solaris.c	(revision 40968)
@@ -0,0 +1,49 @@
+/* $Id$ */
+/** @file
+ * IPRT - Process Management, Ring-0 Driver, Solaris.
+ */
+
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/process.h>
+
+
+
+RTDECL(RTPROCESS) RTProcSelf(void)
+{
+    return ddi_get_pid();
+}
+
+
+RTR0DECL(RTR0PROCESS) RTR0ProcHandleSelf(void)
+{
+    proc_t *pProcess = NULL;
+    drv_getparm(UPROCP, &pProcess);
+    return (RTR0PROCESS)pProcess;
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/solaris/thread-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/thread-r0drv-solaris.c	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/thread-r0drv-solaris.c	(revision 40968)
@@ -0,0 +1,185 @@
+/* $Id$ */
+/** @file
+ * IPRT - Threads, Ring-0 Driver, Solaris.
+ */
+
+/*
+ * Copyright (C) 2006-2009 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/thread.h>
+
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mp.h>
+
+#define SOL_THREAD_PREEMPT       (*((char *)curthread + g_offrtSolThreadPreempt))
+#define SOL_CPU_RUNRUN           (*((char *)CPU + g_offrtSolCpuPreempt))
+#define SOL_CPU_KPRUNRUN         (*((char *)CPU + g_offrtSolCpuForceKernelPreempt))
+
+RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
+{
+    return (RTNATIVETHREAD)curthread;
+}
+
+
+static int rtR0ThreadSolSleepCommon(RTMSINTERVAL cMillies)
+{
+    clock_t cTicks;
+    RT_ASSERT_PREEMPTIBLE();
+
+    if (!cMillies)
+    {
+        RTThreadYield();
+        return VINF_SUCCESS;
+    }
+
+    if (cMillies != RT_INDEFINITE_WAIT)
+        cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
+    else
+        cTicks = 0;
+
+    delay(cTicks);
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies)
+{
+    return rtR0ThreadSolSleepCommon(cMillies);
+}
+
+
+RTDECL(int) RTThreadSleepNoLog(RTMSINTERVAL cMillies)
+{
+    return rtR0ThreadSolSleepCommon(cMillies);
+}
+
+
+RTDECL(bool) RTThreadYield(void)
+{
+    RT_ASSERT_PREEMPTIBLE();
+
+    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
+    RTThreadPreemptDisable(&PreemptState);
+
+    char cThreadPreempt = SOL_THREAD_PREEMPT;
+    char cForcePreempt  = SOL_CPU_KPRUNRUN;
+    bool fWillYield = false;
+    Assert(cThreadPreempt >= 1);
+
+    /*
+     * If we are the last preemption enabler for this thread and if force
+     * preemption is set on the CPU, only then we are guaranteed to be preempted.
+     */
+    if (cThreadPreempt == 1 && cForcePreempt != 0)
+        fWillYield = true;
+
+    RTThreadPreemptRestore(&PreemptState);
+    return fWillYield;
+}
+
+
+RTDECL(bool) RTThreadPreemptIsEnabled(RTTHREAD hThread)
+{
+    Assert(hThread == NIL_RTTHREAD);
+    if (RT_UNLIKELY(g_frtSolInitDone == false))
+    {
+        cmn_err(CE_CONT, "!RTThreadPreemptIsEnabled called before RTR0Init!\n");
+        return true;
+    }
+
+    bool fThreadPreempt = false;
+    if (SOL_THREAD_PREEMPT == 0)
+        fThreadPreempt = true;
+
+    if (!fThreadPreempt)
+        return false;
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+    if (!ASMIntAreEnabled())
+        return false;
+#endif
+    if (getpil() >= DISP_LEVEL)
+        return false;
+    return true;
+}
+
+
+RTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread)
+{
+    Assert(hThread == NIL_RTTHREAD);
+
+    char cPreempt      = SOL_CPU_RUNRUN;
+    char cForcePreempt = SOL_CPU_KPRUNRUN;
+    return (cPreempt != 0 || cForcePreempt != 0);
+}
+
+
+RTDECL(bool) RTThreadPreemptIsPendingTrusty(void)
+{
+    /* yes, RTThreadPreemptIsPending is reliable. */
+    return true;
+}
+
+
+RTDECL(bool) RTThreadPreemptIsPossible(void)
+{
+    /* yes, kernel preemption is possible. */
+    return true;
+}
+
+
+RTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState)
+{
+    AssertPtr(pState);
+
+    SOL_THREAD_PREEMPT++;
+    Assert(SOL_THREAD_PREEMPT >= 1);
+
+    RT_ASSERT_PREEMPT_CPUID_DISABLE(pState);
+}
+
+
+RTDECL(void) RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState)
+{
+    AssertPtr(pState);
+    RT_ASSERT_PREEMPT_CPUID_RESTORE(pState);
+
+    Assert(SOL_THREAD_PREEMPT >= 1);
+    if (--SOL_THREAD_PREEMPT == 0 && SOL_CPU_RUNRUN != 0)
+        kpreempt(KPREEMPT_SYNC);
+}
+
+
+RTDECL(bool) RTThreadIsInInterrupt(RTTHREAD hThread)
+{
+    Assert(hThread == NIL_RTTHREAD);
+    return servicing_interrupt() ? true : false;
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/solaris/thread2-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/thread2-r0drv-solaris.c	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/thread2-r0drv-solaris.c	(revision 40968)
@@ -0,0 +1,128 @@
+/* $Id$ */
+/** @file
+ * IPRT - Threads (Part 2), Ring-0 Driver, Solaris.
+ */
+
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/thread.h>
+#include <iprt/process.h>
+
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include "internal/thread.h"
+
+
+
+DECLHIDDEN(int) rtThreadNativeInit(void)
+{
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(RTTHREAD) RTThreadSelf(void)
+{
+    return rtThreadGetByNative(RTThreadNativeSelf());
+}
+
+
+DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
+{
+    int iPriority;
+    switch (enmType)
+    {
+        case RTTHREADTYPE_INFREQUENT_POLLER:    iPriority = 60;             break;
+        case RTTHREADTYPE_EMULATION:            iPriority = 66;             break;
+        case RTTHREADTYPE_DEFAULT:              iPriority = 72;             break;
+        case RTTHREADTYPE_MSG_PUMP:             iPriority = 78;             break;
+        case RTTHREADTYPE_IO:                   iPriority = 84;             break;
+        case RTTHREADTYPE_TIMER:                iPriority = 99;             break;
+        default:
+            AssertMsgFailed(("enmType=%d\n", enmType));
+            return VERR_INVALID_PARAMETER;
+    }
+
+    kthread_t *pCurThread = curthread;
+    Assert(pCurThread);
+    thread_lock(pCurThread);
+    thread_change_pri(pCurThread, iPriority, 0);
+    thread_unlock(pCurThread);
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
+{
+    NOREF(pThread);
+    /* There is nothing special that needs doing here, but the
+       user really better know what he's cooking. */
+    return VINF_SUCCESS;
+}
+
+
+DECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread)
+{
+    NOREF(pThread);
+}
+
+
+/**
+ * Native thread main function.
+ *
+ * @param   pvThreadInt     The thread structure.
+ */
+static void rtThreadNativeMain(void *pvThreadInt)
+{
+    PRTTHREADINT pThreadInt = (PRTTHREADINT)pvThreadInt;
+
+    rtThreadMain(pThreadInt, RTThreadNativeSelf(), &pThreadInt->szName[0]);
+    thread_exit();
+}
+
+
+DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThreadInt, PRTNATIVETHREAD pNativeThread)
+{
+    RT_ASSERT_PREEMPTIBLE();
+    kthread_t *pThread = thread_create(NULL,                            /* Stack, use base */
+                                       0,                               /* Stack size */
+                                       rtThreadNativeMain,              /* Thread function */
+                                       pThreadInt,                      /* Function data */
+                                       sizeof(pThreadInt),              /* Data size */
+                                       (proc_t *)RTR0ProcHandleSelf(),  /* Process handle */
+                                       TS_RUN,                          /* Ready to run */
+                                       minclsyspri                      /* Priority */
+                                       );
+    if (RT_LIKELY(pThread))
+    {
+        *pNativeThread = (RTNATIVETHREAD)pThread;
+        return VINF_SUCCESS;
+    }
+
+    return VERR_OUT_OF_RESOURCES;
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/solaris/time-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/time-r0drv-solaris.c	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/time-r0drv-solaris.c	(revision 40968)
@@ -0,0 +1,70 @@
+/* $Id$ */
+/** @file
+ * IPRT - Time, Ring-0 Driver, Solaris.
+ */
+
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define RTTIME_INCL_TIMESPEC
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/time.h>
+
+
+RTDECL(uint64_t) RTTimeNanoTS(void)
+{
+    return (uint64_t)gethrtime();
+}
+
+
+RTDECL(uint64_t) RTTimeMilliTS(void)
+{
+    return RTTimeNanoTS() / 1000000;
+}
+
+
+RTDECL(uint64_t) RTTimeSystemNanoTS(void)
+{
+    return RTTimeNanoTS();
+}
+
+
+RTDECL(uint64_t) RTTimeSystemMilliTS(void)
+{
+    return RTTimeNanoTS() / 1000000;
+}
+
+
+RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
+{
+    timestruc_t TimeSpec;
+
+    mutex_enter(&tod_lock);
+    TimeSpec = tod_get();
+    mutex_exit(&tod_lock);
+    return RTTimeSpecSetNano(pTime, (uint64_t)TimeSpec.tv_sec * 1000000000 + TimeSpec.tv_nsec);
+}
+
Index: /trunk/src/VBox/Runtime/r0drv/solaris/timer-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/timer-r0drv-solaris.c	(revision 40968)
+++ /trunk/src/VBox/Runtime/r0drv/solaris/timer-r0drv-solaris.c	(revision 40968)
@@ -0,0 +1,419 @@
+/* $Id$ */
+/** @file
+ * IPRT - Timer, Ring-0 Driver, Solaris.
+ */
+
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "the-solaris-kernel.h"
+#include "internal/iprt.h"
+#include <iprt/timer.h>
+
+#include <iprt/asm.h>
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# include <iprt/asm-amd64-x86.h>
+#endif
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/mp.h>
+#include <iprt/spinlock.h>
+#include <iprt/time.h>
+#include <iprt/thread.h>
+#include "internal/magics.h"
+
+#define SOL_TIMER_ANY_CPU       (-1)
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+/**
+ * Single-CPU timer handle.
+ */
+typedef struct RTR0SINGLETIMERSOL
+{
+    /** Cyclic handler. */
+    cyc_handler_t           hHandler;
+    /** Cyclic time and interval representation. */
+    cyc_time_t              hFireTime;
+    /** Timer ticks. */
+    uint64_t                u64Tick;
+} RTR0SINGLETIMERSOL;
+typedef RTR0SINGLETIMERSOL *PRTR0SINGLETIMERSOL;
+
+/**
+ * Omni-CPU timer handle.
+ */
+typedef struct RTR0OMNITIMERSOL
+{
+    /** Absolute timestamp of when the timer should fire next. */
+    uint64_t                u64When;
+    /** Array of timer ticks per CPU. Reinitialized when a CPU is online'd. */
+    uint64_t               *au64Ticks;
+} RTR0OMNITIMERSOL;
+typedef RTR0OMNITIMERSOL *PRTR0OMNITIMERSOL;
+
+/**
+ * The internal representation of a Solaris timer handle.
+ */
+typedef struct RTTIMER
+{
+    /** Magic.
+     * This is RTTIMER_MAGIC, but changes to something else before the timer
+     * is destroyed to indicate clearly that thread should exit. */
+    uint32_t volatile       u32Magic;
+    /** Flag indicating that the timer is suspended. */
+    uint8_t volatile        fSuspended;
+    /** Whether the timer must run on all CPUs or not. */
+    uint8_t                 fAllCpu;
+    /** Whether the timer must run on a specific CPU or not. */
+    uint8_t                 fSpecificCpu;
+    /** The CPU it must run on if fSpecificCpu is set. */
+    uint8_t                 iCpu;
+    /** The nano second interval for repeating timers. */
+    uint64_t                interval;
+    /** Cyclic timer Id. */
+    cyclic_id_t             hCyclicId;
+    /** @todo Make this a union unless we intend to support omni<=>single timers
+     *        conversions. */
+    /** Single-CPU timer handle. */
+    PRTR0SINGLETIMERSOL     pSingleTimer;
+    /** Omni-CPU timer handle. */
+    PRTR0OMNITIMERSOL       pOmniTimer;
+    /** The user callback. */
+    PFNRTTIMER              pfnTimer;
+    /** The argument for the user callback. */
+    void                   *pvUser;
+} RTTIMER;
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** Validates that the timer is valid. */
+#define RTTIMER_ASSERT_VALID_RET(pTimer) \
+    do \
+    { \
+        AssertPtrReturn(pTimer, VERR_INVALID_HANDLE); \
+        AssertMsgReturn((pTimer)->u32Magic == RTTIMER_MAGIC, ("pTimer=%p u32Magic=%x expected %x\n", (pTimer), (pTimer)->u32Magic, RTTIMER_MAGIC), \
+            VERR_INVALID_HANDLE); \
+    } while (0)
+
+
+/**
+ * Callback wrapper for Omni-CPU and single-CPU timers.
+ *
+ * @param    pvArg              Opaque pointer to the timer.
+ *
+ * @remarks This will be executed in interrupt context but only at the specified
+ *          level i.e. CY_LOCK_LEVEL in our case. We -CANNOT- call into the
+ *          cyclic subsystem here, neither should pfnTimer().
+ */
+static void rtTimerSolCallbackWrapper(void *pvArg)
+{
+    PRTTIMER pTimer = (PRTTIMER)pvArg;
+    AssertPtrReturnVoid(pTimer);
+
+    if (pTimer->pSingleTimer)
+    {
+        uint64_t u64Tick = ++pTimer->pSingleTimer->u64Tick;
+        pTimer->pfnTimer(pTimer, pTimer->pvUser, u64Tick);
+    }
+    else if (pTimer->pOmniTimer)
+    {
+        uint64_t u64Tick = ++pTimer->pOmniTimer->au64Ticks[CPU->cpu_id];
+        pTimer->pfnTimer(pTimer, pTimer->pvUser, u64Tick);
+    }
+}
+
+
+/**
+ * Omni-CPU cyclic online event. This is called before the omni cycle begins to
+ * fire on the specified CPU.
+ *
+ * @param    pvArg              Opaque pointer to the timer.
+ * @param    pCpu               Pointer to the CPU on which it will fire.
+ * @param    pCyclicHandler     Pointer to a cyclic handler to add to the CPU
+ *                              specified in @a pCpu.
+ * @param    pCyclicTime        Pointer to the cyclic time and interval object.
+ *
+ * @remarks We -CANNOT- call back into the cyclic subsystem here, we can however
+ *          block (sleep).
+ */
+static void rtTimerSolOmniCpuOnline(void *pvArg, cpu_t *pCpu, cyc_handler_t *pCyclicHandler, cyc_time_t *pCyclicTime)
+{
+    PRTTIMER pTimer = (PRTTIMER)pvArg;
+    AssertPtrReturnVoid(pTimer);
+    AssertPtrReturnVoid(pCpu);
+    AssertPtrReturnVoid(pCyclicHandler);
+    AssertPtrReturnVoid(pCyclicTime);
+
+    pTimer->pOmniTimer->au64Ticks[pCpu->cpu_id] = 0;
+    pCyclicHandler->cyh_func  = rtTimerSolCallbackWrapper;
+    pCyclicHandler->cyh_arg   = pTimer;
+    pCyclicHandler->cyh_level = CY_LOCK_LEVEL;
+
+    uint64_t u64Now = RTTimeNanoTS();
+    if (pTimer->pOmniTimer->u64When < u64Now)
+        pCyclicTime->cyt_when = u64Now + pTimer->interval / 2;
+    else
+        pCyclicTime->cyt_when = pTimer->pOmniTimer->u64When;
+
+    pCyclicTime->cyt_interval = pTimer->interval;
+}
+
+
+RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser)
+{
+    RT_ASSERT_PREEMPTIBLE();
+    *ppTimer = NULL;
+
+    /*
+     * Validate flags.
+     */
+    if (!RTTIMER_FLAGS_ARE_VALID(fFlags))
+        return VERR_INVALID_PARAMETER;
+
+    if (    (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC)
+        &&  (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL
+        &&  !RTMpIsCpuPossible(RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK)))
+        return VERR_CPU_NOT_FOUND;
+
+    if ((fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL && u64NanoInterval == 0)
+        return VERR_NOT_SUPPORTED;
+
+    /*
+     * Allocate and initialize the timer handle.
+     */
+    PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer));
+    if (!pTimer)
+        return VERR_NO_MEMORY;
+
+    pTimer->u32Magic = RTTIMER_MAGIC;
+    pTimer->fSuspended = true;
+    if ((fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL)
+    {
+        pTimer->fAllCpu = true;
+        pTimer->fSpecificCpu = false;
+        pTimer->iCpu = 255;
+    }
+    else if (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC)
+    {
+        pTimer->fAllCpu = false;
+        pTimer->fSpecificCpu = true;
+        pTimer->iCpu = fFlags & RTTIMER_FLAGS_CPU_MASK; /* ASSUMES: index == cpuid */
+    }
+    else
+    {
+        pTimer->fAllCpu = false;
+        pTimer->fSpecificCpu = false;
+        pTimer->iCpu = 255;
+    }
+    pTimer->interval = u64NanoInterval;
+    pTimer->pfnTimer = pfnTimer;
+    pTimer->pvUser = pvUser;
+    pTimer->pSingleTimer = NULL;
+    pTimer->pOmniTimer = NULL;
+    pTimer->hCyclicId = CYCLIC_NONE;
+
+    cmn_err(CE_NOTE, "Create pTimer->u32Magic=%x RTTIMER_MAGIC=%x\n",  pTimer->u32Magic, RTTIMER_MAGIC);
+    *ppTimer = pTimer;
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTTimerDestroy(PRTTIMER pTimer)
+{
+    if (pTimer == NULL)
+        return VINF_SUCCESS;
+    RTTIMER_ASSERT_VALID_RET(pTimer);
+    RT_ASSERT_INTS_ON();
+
+    /*
+     * Free the associated resources.
+     */
+    RTTimerStop(pTimer);
+    ASMAtomicWriteU32(&pTimer->u32Magic, ~RTTIMER_MAGIC);
+    RTMemFree(pTimer);
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First)
+{
+    cmn_err(CE_NOTE, "Start pTimer->u32Magic=%x RTTIMER_MAGIC=%x\n",  pTimer->u32Magic, RTTIMER_MAGIC);
+    RTTIMER_ASSERT_VALID_RET(pTimer);
+    RT_ASSERT_INTS_ON();
+
+    if (!pTimer->fSuspended)
+        return VERR_TIMER_ACTIVE;
+
+    /* One-shot timers are not supported by the cyclic system. */
+    if (pTimer->interval == 0)
+        return VERR_NOT_SUPPORTED;
+
+    pTimer->fSuspended = false;
+    if (pTimer->fAllCpu)
+    {
+        PRTR0OMNITIMERSOL pOmniTimer = RTMemAllocZ(sizeof(RTR0OMNITIMERSOL));
+        if (RT_UNLIKELY(!pOmniTimer))
+            return VERR_NO_MEMORY;
+
+        pOmniTimer->au64Ticks = RTMemAllocZ(RTMpGetCount() * sizeof(uint64_t));
+        if (RT_UNLIKELY(!pOmniTimer->au64Ticks))
+        {
+            RTMemFree(pOmniTimer);
+            return VERR_NO_MEMORY;
+        }
+
+        /*
+         * Setup omni (all CPU) timer. The Omni-CPU online event will fire
+         * and from there we setup periodic timers per CPU.
+         */
+        pTimer->pOmniTimer = pOmniTimer;
+        pOmniTimer->u64When     = pTimer->interval + RTTimeNanoTS();
+
+        cyc_omni_handler_t hOmni;
+        hOmni.cyo_online        = rtTimerSolOmniCpuOnline;
+        hOmni.cyo_offline       = NULL;
+        hOmni.cyo_arg           = pTimer;
+
+        mutex_enter(&cpu_lock);
+        pTimer->hCyclicId = cyclic_add_omni(&hOmni);
+        mutex_exit(&cpu_lock);
+    }
+    else
+    {
+        int iCpu = SOL_TIMER_ANY_CPU;
+        if (pTimer->fSpecificCpu)
+        {
+            iCpu = pTimer->iCpu;
+            if (!RTMpIsCpuOnline(iCpu))    /* ASSUMES: index == cpuid */
+                return VERR_CPU_OFFLINE;
+        }
+
+        PRTR0SINGLETIMERSOL pSingleTimer = RTMemAllocZ(sizeof(RTR0SINGLETIMERSOL));
+        if (RT_UNLIKELY(!pSingleTimer))
+            return VERR_NO_MEMORY;
+
+        pTimer->pSingleTimer = pSingleTimer;
+        pSingleTimer->hHandler.cyh_func  = rtTimerSolCallbackWrapper;
+        pSingleTimer->hHandler.cyh_arg   = pTimer;
+        pSingleTimer->hHandler.cyh_level = CY_LOCK_LEVEL;
+
+        mutex_enter(&cpu_lock);
+        if (iCpu != SOL_TIMER_ANY_CPU && !cpu_is_online(cpu[iCpu]))
+        {
+            mutex_exit(&cpu_lock);
+            RTMemFree(pSingleTimer);
+            pTimer->pSingleTimer = NULL;
+            return VERR_CPU_OFFLINE;
+        }
+
+        pSingleTimer->hFireTime.cyt_when = u64First + RTTimeNanoTS();
+        if (pTimer->interval == 0)
+        {
+            /* @todo use gethrtime_max instead of LLONG_MAX? */
+            AssertCompileSize(pSingleTimer->hFireTime.cyt_interval, sizeof(long long));
+            pSingleTimer->hFireTime.cyt_interval = LLONG_MAX - pSingleTimer->hFireTime.cyt_when;
+        }
+        else
+            pSingleTimer->hFireTime.cyt_interval = pTimer->interval;
+
+        pTimer->hCyclicId = cyclic_add(&pSingleTimer->hHandler, &pSingleTimer->hFireTime);
+        if (iCpu != SOL_TIMER_ANY_CPU)
+            cyclic_bind(pTimer->hCyclicId, cpu[iCpu], NULL /* cpupart */);
+
+        mutex_exit(&cpu_lock);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTTimerStop(PRTTIMER pTimer)
+{
+    RTTIMER_ASSERT_VALID_RET(pTimer);
+    RT_ASSERT_INTS_ON();
+
+    if (pTimer->fSuspended)
+        return VERR_TIMER_SUSPENDED;
+
+    pTimer->fSuspended = true;
+    if (pTimer->pSingleTimer)
+    {
+        mutex_enter(&cpu_lock);
+        cyclic_remove(pTimer->hCyclicId);
+        mutex_exit(&cpu_lock);
+        RTMemFree(pTimer->pSingleTimer);
+    }
+    else if (pTimer->pOmniTimer)
+    {
+        mutex_enter(&cpu_lock);
+        cyclic_remove(pTimer->hCyclicId);
+        mutex_exit(&cpu_lock);
+        RTMemFree(pTimer->pOmniTimer->au64Ticks);
+        RTMemFree(pTimer->pOmniTimer);
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval)
+{
+    RTTIMER_ASSERT_VALID_RET(pTimer);
+
+    /** @todo implement me! */
+
+    return VERR_NOT_SUPPORTED;
+}
+
+
+RTDECL(uint32_t) RTTimerGetSystemGranularity(void)
+{
+    return nsec_per_tick;
+}
+
+
+RTDECL(int) RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted)
+{
+    return VERR_NOT_SUPPORTED;
+}
+
+
+RTDECL(int) RTTimerReleaseSystemGranularity(uint32_t u32Granted)
+{
+    return VERR_NOT_SUPPORTED;
+}
+
+
+RTDECL(bool) RTTimerCanDoHighResolution(void)
+{
+    /** @todo return true; - when missing bits have been implemented and tested*/
+    return false;
+}
+
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/RTMpPokeCpu-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/RTMpPokeCpu-r0drv-solaris.c	(revision 40967)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - RTMpPokeCpu, Solaris Implementation.
- */
-
-/*
- * Copyright (C) 2009 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "../the-solaris-kernel.h"
-#include "internal/iprt.h"
-#include <iprt/mp.h>
-
-#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
-# include <iprt/asm-amd64-x86.h>
-#endif
-#include <iprt/assert.h>
-#include <iprt/err.h>
-
-
-
-RTDECL(int) RTMpPokeCpu(RTCPUID idCpu)
-{
-    RT_ASSERT_INTS_ON();
-    if (idCpu < ncpus)
-        poke_cpu(idCpu);
-    return VINF_SUCCESS;
-}
-
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/alloc-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/alloc-r0drv-solaris.c	(revision 40967)
+++ 	(revision )
@@ -1,206 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - Memory Allocation, Ring-0 Driver, Solaris.
- */
-
-/*
- * Copyright (C) 2006-2010 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "../the-solaris-kernel.h"
-#include "internal/iprt.h"
-#include <iprt/mem.h>
-
-#include <iprt/assert.h>
-#include <iprt/err.h>
-#include <iprt/log.h>
-#include <iprt/param.h>
-#include <iprt/thread.h>
-#include "r0drv/alloc-r0drv.h"
-
-
-/*******************************************************************************
-*   Structures and Typedefs                                                    *
-*******************************************************************************/
-static ddi_dma_attr_t s_rtR0SolDmaAttr =
-{
-    DMA_ATTR_V0,                /* Version Number */
-    (uint64_t)0,                /* Lower limit */
-    (uint64_t)0,                /* High limit */
-    (uint64_t)0xffffffff,       /* Counter limit */
-    (uint64_t)PAGESIZE,         /* Alignment */
-    (uint64_t)PAGESIZE,         /* Burst size */
-    (uint64_t)PAGESIZE,         /* Effective DMA size */
-    (uint64_t)0xffffffff,       /* Max DMA xfer size */
-    (uint64_t)0xffffffff,       /* Segment boundary */
-    1,                          /* Scatter-gather list length (1 for contiguous) */
-    1,                          /* Device granularity */
-    0                           /* Bus-specific flags */
-};
-
-extern void *contig_alloc(size_t cb, ddi_dma_attr_t *pDmaAttr, size_t uAlign, int fCanSleep);
-
-
-/**
- * OS specific allocation function.
- */
-DECLHIDDEN(int) rtR0MemAllocEx(size_t cb, uint32_t fFlags, PRTMEMHDR *ppHdr)
-{
-    size_t      cbAllocated = cb;
-    PRTMEMHDR   pHdr;
-
-#ifdef RT_ARCH_AMD64
-    if (fFlags & RTMEMHDR_FLAG_EXEC)
-    {
-        AssertReturn(!(fFlags & RTMEMHDR_FLAG_ANY_CTX), NULL);
-        cbAllocated = RT_ALIGN_Z(cb + sizeof(*pHdr), PAGE_SIZE) - sizeof(*pHdr);
-        pHdr = (PRTMEMHDR)segkmem_alloc(heaptext_arena, cbAllocated + sizeof(*pHdr), KM_SLEEP);
-    }
-    else
-#endif
-    {
-        unsigned fKmFlags = fFlags & RTMEMHDR_FLAG_ANY_CTX_ALLOC ? KM_NOSLEEP : KM_SLEEP;
-        if (fFlags & RTMEMHDR_FLAG_ZEROED)
-            pHdr = (PRTMEMHDR)kmem_zalloc(cb + sizeof(*pHdr), fKmFlags);
-        else
-            pHdr = (PRTMEMHDR)kmem_alloc(cb + sizeof(*pHdr), fKmFlags);
-    }
-    if (RT_UNLIKELY(!pHdr))
-    {
-        LogRel(("rtMemAllocEx(%u, %#x) failed\n", (unsigned)cb + sizeof(*pHdr), fFlags));
-        return VERR_NO_MEMORY;
-    }
-
-    pHdr->u32Magic  = RTMEMHDR_MAGIC;
-    pHdr->fFlags    = fFlags;
-    pHdr->cb        = cbAllocated;
-    pHdr->cbReq     = cb;
-
-    *ppHdr = pHdr;
-    return VINF_SUCCESS;
-}
-
-
-/**
- * OS specific free function.
- */
-DECLHIDDEN(void) rtR0MemFree(PRTMEMHDR pHdr)
-{
-    pHdr->u32Magic += 1;
-#ifdef RT_ARCH_AMD64
-    if (pHdr->fFlags & RTMEMHDR_FLAG_EXEC)
-        segkmem_free(heaptext_arena, pHdr, pHdr->cb + sizeof(*pHdr));
-    else
-#endif
-        kmem_free(pHdr, pHdr->cb + sizeof(*pHdr));
-}
-
-
-/**
- * Allocates physical memory which satisfy the given constraints.
- *
- * @param   uPhysHi        The upper physical address limit (inclusive).
- * @param   puPhys         Where to store the physical address of the allocated
- *                         memory. Optional, can be NULL.
- * @param   cb             Size of allocation.
- * @param   uAlignment     Alignment.
- * @param   fContig        Whether the memory must be physically contiguous or
- *                         not.
- *
- * @returns Virtual address of allocated memory block or NULL if allocation
- *        failed.
- */
-DECLHIDDEN(void *) rtR0SolMemAlloc(uint64_t uPhysHi, uint64_t *puPhys, size_t cb, uint64_t uAlignment, bool fContig)
-{
-    if ((cb & PAGEOFFSET) != 0)
-        return NULL;
-
-    size_t cPages = (cb + PAGESIZE - 1) >> PAGESHIFT;
-    if (!cPages)
-        return NULL;
-
-    ddi_dma_attr_t DmaAttr = s_rtR0SolDmaAttr;
-    DmaAttr.dma_attr_addr_hi    = uPhysHi;
-    DmaAttr.dma_attr_align      = uAlignment;
-    if (!fContig)
-        DmaAttr.dma_attr_sgllen = cPages > INT_MAX ? INT_MAX - 1 : cPages;
-    else
-        AssertRelease(DmaAttr.dma_attr_sgllen == 1);
-
-    void *pvMem = contig_alloc(cb, &DmaAttr, PAGESIZE, 1 /* can sleep */);
-    if (!pvMem)
-    {
-        LogRel(("rtR0SolMemAlloc failed. cb=%u Align=%u fContig=%d\n", (unsigned)cb, (unsigned)uAlignment, fContig));
-        return NULL;
-    }
-
-    pfn_t PageFrameNum = hat_getpfnum(kas.a_hat, (caddr_t)pvMem);
-    AssertRelease(PageFrameNum != PFN_INVALID);
-    if (puPhys)
-        *puPhys = (uint64_t)PageFrameNum << PAGESHIFT;
-
-    return pvMem;
-}
-
-
-/**
- * Frees memory allocated using rtR0SolMemAlloc().
- *
- * @param   pv         The memory to free.
- * @param   cb         Size of the memory block
- */
-DECLHIDDEN(void) rtR0SolMemFree(void *pv, size_t cb)
-{
-    if (RT_LIKELY(pv))
-        g_pfnrtR0Sol_contig_free(pv, cb);
-}
-
-
-RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb)
-{
-    AssertPtrReturn(pPhys, NULL);
-    AssertReturn(cb > 0, NULL);
-    RT_ASSERT_PREEMPTIBLE();
-
-    /* Allocate physically contiguous (< 4GB) page-aligned memory. */
-    uint64_t uPhys;
-    void *pvMem = rtR0SolMemAlloc((uint64_t)_4G - 1, &uPhys, cb, PAGESIZE, true);
-    if (RT_UNLIKELY(!pvMem))
-    {
-        LogRel(("RTMemContAlloc failed to allocate %u bytes\n", cb));
-        return NULL;
-    }
-
-    Assert(uPhys < _4G);
-    *pPhys = uPhys;
-    return pvMem;
-}
-
-
-RTR0DECL(void) RTMemContFree(void *pv, size_t cb)
-{
-    RT_ASSERT_PREEMPTIBLE();
-    rtR0SolMemFree(pv, cb);
-}
-
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/memobj-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/memobj-r0drv-solaris.c	(revision 40967)
+++ 	(revision )
@@ -1,1051 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - Ring-0 Memory Objects, Solaris.
- */
-
-/*
- * Copyright (C) 2006-2007 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "../the-solaris-kernel.h"
-#include "internal/iprt.h"
-#include <iprt/memobj.h>
-
-#include <iprt/asm.h>
-#include <iprt/assert.h>
-#include <iprt/err.h>
-#include <iprt/log.h>
-#include <iprt/mem.h>
-#include <iprt/param.h>
-#include <iprt/process.h>
-#include "internal/memobj.h"
-#include "memobj-r0drv-solaris.h"
-
-#define SOL_IS_KRNL_ADDR(vx)    ((uintptr_t)(vx) >= kernelbase)
-static vnode_t                  s_PageVnode;
-
-/*******************************************************************************
-*   Structures and Typedefs                                                    *
-*******************************************************************************/
-/**
- * The Solaris version of the memory object structure.
- */
-typedef struct RTR0MEMOBJSOL
-{
-    /** The core structure. */
-    RTR0MEMOBJINTERNAL  Core;
-    /** Pointer to kernel memory cookie. */
-    ddi_umem_cookie_t   Cookie;
-    /** Shadow locked pages. */
-    void               *pvHandle;
-    /** Access during locking. */
-    int                 fAccess;
-    /** Set if large pages are involved in an RTR0MEMOBJTYPE_PHYS
-     *  allocation. */
-    bool                fLargePage;
-} RTR0MEMOBJSOL, *PRTR0MEMOBJSOL;
-
-
-/**
- * Returns the physical address for a virtual address.
- *
- * @param pv        The virtual address.
- *
- * @returns The physical address corresponding to @a pv.
- */
-static uint64_t rtR0MemObjSolVirtToPhys(void *pv)
-{
-    struct hat *pHat         = NULL;
-    pfn_t       PageFrameNum = 0;
-    uintptr_t   uVirtAddr    = (uintptr_t)pv;
-
-    if (SOL_IS_KRNL_ADDR(pv))
-        pHat = kas.a_hat;
-    else
-    {
-        proc_t *pProcess = (proc_t *)RTR0ProcHandleSelf();
-        AssertRelease(pProcess);
-        pHat = pProcess->p_as->a_hat;
-    }
-
-    PageFrameNum = hat_getpfnum(pHat, (caddr_t)(uVirtAddr & PAGEMASK));
-    AssertReleaseMsg(PageFrameNum != PFN_INVALID, ("rtR0MemObjSolVirtToPhys failed. pv=%p\n", pv));
-    return (((uint64_t)PageFrameNum << PAGESHIFT) | (uVirtAddr & PAGEOFFSET));
-}
-
-
-/**
- * Returns the physical address of a page from an array of pages.
- *
- * @param ppPages       The array of pages.
- * @param iPage         Index of the page in the array to get the physical
- *                      address.
- *
- * @returns Physical address of specific page within the list of pages specified
- *         in @a ppPages.
- */
-static inline uint64_t rtR0MemObjSolPageToPhys(page_t **ppPages, size_t iPage)
-{
-    pfn_t PageFrameNum = page_pptonum(ppPages[iPage]);
-    AssertReleaseMsg(PageFrameNum != PFN_INVALID, ("rtR0MemObjSolPageToPhys failed. ppPages=%p iPage=%u\n", ppPages, iPage));
-    return (uint64_t)PageFrameNum << PAGESHIFT;
-}
-
-
-/**
- * Retreives a free page from the kernel freelist.
- *
- * @param virtAddr       The virtual address to which this page maybe mapped in
- *                       the future.
- * @param cbPage         The size of the page.
- *
- * @returns Pointer to the allocated page, NULL on failure.
- */
-static page_t *rtR0MemObjSolPageFromFreelist(caddr_t virtAddr, size_t cbPage)
-{
-    seg_t KernelSeg;
-    KernelSeg.s_as = &kas;
-    page_t *pPage = page_get_freelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
-                                      cbPage, 0 /* flags */, NULL /* NUMA group */);
-    if (   !pPage
-        && g_frtSolUseKflt)
-    {
-        pPage = page_get_freelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
-                                  cbPage, 0x200 /* PG_KFLT */, NULL /* NUMA group */);
-    }
-    return pPage;
-}
-
-
-/**
- * Retrieves a free page from the kernel cachelist.
- *
- * @param virtAddr      The virtual address to which this page maybe mapped in
- *                      the future.
- * @param cbPage        The size of the page.
- *
- * @return Pointer to the allocated page, NULL on failure.
- */
-static page_t *rtR0MemObjSolPageFromCachelist(caddr_t virtAddr, size_t cbPage)
-{
-    seg_t KernelSeg;
-    KernelSeg.s_as = &kas;
-    page_t *pPage = page_get_cachelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
-                                       0 /* flags */, NULL /* NUMA group */);
-    if (   !pPage
-        && g_frtSolUseKflt)
-    {
-        pPage = page_get_cachelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
-                                   0x200 /* PG_KFLT */, NULL /* NUMA group */);
-    }
-
-    /*
-     * Remove association with the vnode for pages from the cachelist.
-     */
-    if (!PP_ISAGED(pPage))
-        page_hashout(pPage, NULL /* mutex */);
-
-    return pPage;
-}
-
-
-/**
- * Allocates physical non-contiguous memory.
- *
- * @param uPhysHi   The upper physical address limit (inclusive).
- * @param puPhys    Where to store the physical address of first page. Optional,
- *                  can be NULL.
- * @param cb        The size of the allocation.
- *
- * @return Array of allocated pages, NULL on failure.
- */
-static page_t **rtR0MemObjSolPagesAlloc(uint64_t uPhysHi, uint64_t *puPhys, size_t cb)
-{
-    /** @todo We need to satisfy the upper physical address constraint */
-
-    /*
-     * The page freelist and cachelist both hold pages that are not mapped into any address space.
-     * The cachelist is not really free pages but when memory is exhausted they'll be moved to the
-     * free lists, it's the total of the free+cache list that we see on the 'free' column in vmstat.
-     *
-     * Reserve available memory for pages and create the pages.
-     */
-    pgcnt_t cPages = (cb + PAGESIZE - 1) >> PAGESHIFT;
-    int rc = page_resv(cPages, KM_NOSLEEP);
-    if (rc)
-    {
-        rc = page_create_wait(cPages, 0 /* flags */);
-        if (rc)
-        {
-            size_t   cbPages = cPages * sizeof(page_t *);
-            page_t **ppPages = kmem_zalloc(cbPages, KM_SLEEP);
-            if (RT_LIKELY(ppPages))
-            {
-                /*
-                 * Get pages from kseg, the 'virtAddr' here is only for colouring but unfortunately
-                 * we don't yet have the 'virtAddr' to which this memory may be mapped.
-                 */
-                caddr_t virtAddr = NULL;
-                for (size_t i = 0; i < cPages; i++, virtAddr += PAGESIZE)
-                {
-                    /*
-                     * Get a page from the freelist or cachelist.
-                     */
-                    page_t *pPage = rtR0MemObjSolPageFromFreelist(virtAddr, PAGESIZE);
-                    if (!pPage)
-                        pPage = rtR0MemObjSolPageFromCachelist(virtAddr, PAGESIZE);
-                    if (RT_UNLIKELY(!pPage))
-                    {
-                        /*
-                         * No more pages found, release was grabbed so far.
-                         */
-                        page_create_putback(cPages - i);
-                        while (--i >= 0)
-                            page_free(ppPages[i], 0 /* don't need page, move to tail of pagelist */);
-                        kmem_free(ppPages, cbPages);
-                        page_unresv(cPages);
-                        return NULL;
-                    }
-
-                    PP_CLRFREE(pPage);      /* Page is no longer free */
-                    PP_CLRAGED(pPage);      /* Page is not hashed in */
-                    ppPages[i] = pPage;
-                }
-
-                /*
-                 * We now have the pages locked exclusively, before they are mapped in
-                 * we must downgrade the lock.
-                 */
-                if (puPhys)
-                    *puPhys = (uint64_t)page_pptonum(ppPages[0]) << PAGESHIFT;
-                return ppPages;
-            }
-
-            page_create_putback(cPages);
-        }
-
-        page_unresv(cPages);
-    }
-
-    return NULL;
-}
-
-
-/**
- * Prepares pages allocated by rtR0MemObjSolPagesAlloc for mapping.
- *
- * @param    ppPages    Pointer to the page list.
- * @param    cb         Size of the allocation.
- * @param    auPhys     Where to store the physical address of the premapped
- *                      pages.
- * @param    cPages     The number of pages (entries) in @a auPhys.
- *
- * @returns IPRT status code.
- */
-static int rtR0MemObjSolPagesPreMap(page_t **ppPages, size_t cb, uint64_t auPhys[], size_t cPages)
-{
-    AssertPtrReturn(ppPages, VERR_INVALID_PARAMETER);
-    AssertPtrReturn(auPhys, VERR_INVALID_PARAMETER);
-
-    for (size_t iPage = 0; iPage < cPages; iPage++)
-    {
-        /*
-         * Prepare pages for mapping into kernel/user-space. Downgrade the
-         * exclusive page lock to a shared lock if necessary.
-         */
-        if (page_tryupgrade(ppPages[iPage]) == 1)
-            page_downgrade(ppPages[iPage]);
-
-        auPhys[iPage] = rtR0MemObjSolPageToPhys(ppPages, iPage);
-    }
-
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Frees pages allocated by rtR0MemObjSolPagesAlloc.
- *
- * @param ppPages       Pointer to the page list.
- * @param cbPages       Size of the allocation.
- */
-static void rtR0MemObjSolPagesFree(page_t **ppPages, size_t cb)
-{
-    size_t cPages  = (cb + PAGESIZE - 1) >> PAGESHIFT;
-    size_t cbPages = cPages * sizeof(page_t *);
-    for (size_t iPage = 0; iPage < cPages; iPage++)
-    {
-        /*
-         *  We need to exclusive lock the pages before freeing them.
-         */
-        int rc = page_tryupgrade(ppPages[iPage]);
-        if (!rc)
-        {
-            page_unlock(ppPages[iPage]);
-            while (!page_lock(ppPages[iPage], SE_EXCL, NULL /* mutex */, P_RECLAIM))
-            {
-                /* nothing */;
-            }
-        }
-        page_free(ppPages[iPage], 0 /* don't need page, move to tail of pagelist */);
-    }
-    kmem_free(ppPages, cbPages);
-    page_unresv(cPages);
-}
-
-
-/**
- * Allocates a large page to cover the required allocation size.
- *
- * @param puPhys        Where to store the physical address of the allocated
- *                      page. Optional, can be NULL.
- * @param cb            Size of the allocation.
- *
- * @returns Pointer to the allocated large page, NULL on failure.
- */
-static page_t *rtR0MemObjSolLargePageAlloc(uint64_t *puPhys, size_t cb)
-{
-    /*
-     * Reserve available memory and create the sub-pages.
-     */
-    const pgcnt_t cPages = cb >> PAGESHIFT;
-    int rc = page_resv(cPages, KM_NOSLEEP);
-    if (rc)
-    {
-        rc = page_create_wait(cPages, 0 /* flags */);
-        if (rc)
-        {
-            /*
-             * Get a page off the free list. We set virtAddr to 0 since we don't know where
-             * the memory is going to be mapped.
-             */
-            seg_t KernelSeg;
-            caddr_t virtAddr  = NULL;
-            KernelSeg.s_as    = &kas;
-            page_t *pRootPage = rtR0MemObjSolPageFromFreelist(virtAddr, cb);
-            if (pRootPage)
-            {
-                AssertMsg(!(page_pptonum(pRootPage) & (cPages - 1)), ("%p:%lx cPages=%lx\n", pRootPage, page_pptonum(pRootPage), cPages));
-
-                /*
-                 * Mark all the sub-pages as non-free and not-hashed-in.
-                 * It is paramount that we destroy the list (before freeing it).
-                 */
-                page_t *pPageList = pRootPage;
-                for (size_t iPage = 0; iPage < cPages; iPage++)
-                {
-                    page_t *pPage = pPageList;
-                    AssertPtr(pPage);
-                    AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
-                        ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
-                    page_sub(&pPageList, pPage);
-
-                    /*
-                     * Ensure page is now be free and the page size-code must match that of the root page.
-                     */
-                    AssertMsg(PP_ISFREE(pPage), ("%p\n", pPage));
-                    AssertMsg(pPage->p_szc == pRootPage->p_szc, ("%p - %d expected %d \n", pPage, pPage->p_szc, pRootPage->p_szc));
-
-                    PP_CLRFREE(pPage);      /* Page no longer free */
-                    PP_CLRAGED(pPage);      /* Page no longer hashed-in */
-                }
-
-                uint64_t uPhys = (uint64_t)page_pptonum(pRootPage) << PAGESHIFT;
-                AssertMsg(!(uPhys & (cb - 1)), ("%llx %zx\n", uPhys, cb));
-                if (puPhys)
-                    *puPhys = uPhys;
-
-                return pRootPage;
-            }
-
-            page_create_putback(cPages);
-        }
-
-        page_unresv(cPages);
-    }
-
-    return NULL;
-}
-
-
-/**
- * Prepares the large page allocated by rtR0MemObjSolLargePageAlloc to be mapped.
- *
- * @param    pRootPage      Pointer to the root page.
- * @param    cb             Size of the allocation.
- *
- * @returns IPRT status code.
- */
-static int rtR0MemObjSolLargePagePreMap(page_t *pRootPage, size_t cb)
-{
-    const pgcnt_t cPages = cb >> PAGESHIFT;
-
-    Assert(page_get_pagecnt(pRootPage->p_szc) == cPages);
-    AssertMsg(!(page_pptonum(pRootPage) & (cPages - 1)), ("%p:%lx npages=%lx\n", pRootPage, page_pptonum(pRootPage), cPages));
-
-    /*
-     * We need to downgrade the sub-pages from exclusive to shared locking
-     * because otherweise we cannot <you go figure>.
-     */
-    for (pgcnt_t iPage = 0; iPage < cPages; iPage++)
-    {
-        page_t *pPage = page_nextn(pRootPage, iPage);
-        AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
-            ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
-        AssertMsg(!PP_ISFREE(pPage), ("%p\n", pPage));
-
-        if (page_tryupgrade(pPage) == 1)
-            page_downgrade(pPage);
-        AssertMsg(!PP_ISFREE(pPage), ("%p\n", pPage));
-    }
-
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Frees the page allocated by rtR0MemObjSolLargePageAlloc.
- *
- * @param    pRootPage      Pointer to the root page.
- * @param    cb             Allocated size.
- */
-static void rtR0MemObjSolLargePageFree(page_t *pRootPage, size_t cb)
-{
-    pgcnt_t cPages = cb >> PAGESHIFT;
-
-    Assert(page_get_pagecnt(pRootPage->p_szc) == cPages);
-    AssertMsg(!(page_pptonum(pRootPage) & (cPages - 1)), ("%p:%lx cPages=%lx\n", pRootPage, page_pptonum(pRootPage), cPages));
-
-    /*
-     * We need to exclusively lock the sub-pages before freeing the large one.
-     */
-    for (pgcnt_t iPage = 0; iPage < cPages; iPage++)
-    {
-        page_t *pPage = page_nextn(pRootPage, iPage);
-        AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
-                  ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
-        AssertMsg(!PP_ISFREE(pPage), ("%p\n", pPage));
-
-        int rc = page_tryupgrade(pPage);
-        if (!rc)
-        {
-            page_unlock(pPage);
-            while (!page_lock(pPage, SE_EXCL, NULL /* mutex */, P_RECLAIM))
-            {
-                /* nothing */;
-            }
-        }
-    }
-
-    /*
-     * Free the large page and unreserve the memory.
-     */
-    page_free_pages(pRootPage);
-    page_unresv(cPages);
-
-}
-
-
-/**
- * Unmaps kernel/user-space mapped memory.
- *
- * @param    pv         Pointer to the mapped memory block.
- * @param    cb         Size of the memory block.
- */
-static void rtR0MemObjSolUnmap(void *pv, size_t cb)
-{
-    if (SOL_IS_KRNL_ADDR(pv))
-    {
-        hat_unload(kas.a_hat, pv, cb, HAT_UNLOAD | HAT_UNLOAD_UNLOCK);
-        vmem_free(heap_arena, pv, cb);
-    }
-    else
-    {
-        struct as *pAddrSpace = ((proc_t *)RTR0ProcHandleSelf())->p_as;
-        AssertPtr(pAddrSpace);
-        as_rangelock(pAddrSpace);
-        as_unmap(pAddrSpace, pv, cb);
-        as_rangeunlock(pAddrSpace);
-    }
-}
-
-
-/**
- * Lock down memory mappings for a virtual address.
- *
- * @param    pv             Pointer to the memory to lock down.
- * @param    cb             Size of the memory block.
- * @param    fAccess        Page access rights (S_READ, S_WRITE, S_EXEC)
- *
- * @returns IPRT status code.
- */
-static int rtR0MemObjSolLock(void *pv, size_t cb, int fPageAccess)
-{
-    /*
-     * Kernel memory mappings on x86/amd64 are always locked, only handle user-space memory.
-     */
-    if (!SOL_IS_KRNL_ADDR(pv))
-    {
-        proc_t *pProc = (proc_t *)RTR0ProcHandleSelf();
-        AssertPtr(pProc);
-        faultcode_t rc = as_fault(pProc->p_as->a_hat, pProc->p_as, (caddr_t)pv, cb, F_SOFTLOCK, fPageAccess);
-        if (rc)
-        {
-            LogRel(("rtR0MemObjSolLock failed for pv=%pv cb=%lx fPageAccess=%d rc=%d\n", pv, cb, fPageAccess, rc));
-            return VERR_LOCK_FAILED;
-        }
-    }
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Unlock memory mappings for a virtual address.
- *
- * @param    pv             Pointer to the locked memory.
- * @param    cb             Size of the memory block.
- * @param    fPageAccess    Page access rights (S_READ, S_WRITE, S_EXEC).
- */
-static void rtR0MemObjSolUnlock(void *pv, size_t cb, int fPageAccess)
-{
-    if (!SOL_IS_KRNL_ADDR(pv))
-    {
-        proc_t *pProcess = (proc_t *)RTR0ProcHandleSelf();
-        AssertPtr(pProcess);
-        as_fault(pProcess->p_as->a_hat, pProcess->p_as, (caddr_t)pv, cb, F_SOFTUNLOCK, fPageAccess);
-    }
-}
-
-
-/**
- * Maps a list of physical pages into user address space.
- *
- * @param    pVirtAddr      Where to store the virtual address of the mapping.
- * @param    fPageAccess    Page access rights (PROT_READ, PROT_WRITE,
- *                          PROT_EXEC)
- * @param    paPhysAddrs    Array of physical addresses to pages.
- * @param    cb             Size of memory being mapped.
- *
- * @returns IPRT status code.
- */
-static int rtR0MemObjSolUserMap(caddr_t *pVirtAddr, unsigned fPageAccess, uint64_t *paPhysAddrs, size_t cb)
-{
-    struct as *pAddrSpace = ((proc_t *)RTR0ProcHandleSelf())->p_as;
-    int rc = VERR_INTERNAL_ERROR;
-    SEGVBOX_CRARGS Args;
-
-    Args.paPhysAddrs = paPhysAddrs;
-    Args.fPageAccess = fPageAccess;
-
-    as_rangelock(pAddrSpace);
-    map_addr(pVirtAddr, cb, 0 /* offset */, 0 /* vacalign */, MAP_SHARED);
-    if (*pVirtAddr != NULL)
-        rc = as_map(pAddrSpace, *pVirtAddr, cb, rtR0SegVBoxSolCreate, &Args);
-    else
-        rc = ENOMEM;
-    as_rangeunlock(pAddrSpace);
-
-    return RTErrConvertFromErrno(rc);
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
-{
-    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)pMem;
-
-    switch (pMemSolaris->Core.enmType)
-    {
-        case RTR0MEMOBJTYPE_LOW:
-            rtR0SolMemFree(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
-            break;
-
-        case RTR0MEMOBJTYPE_PHYS:
-            if (pMemSolaris->Core.u.Phys.fAllocated)
-            {
-                if (pMemSolaris->fLargePage)
-                    rtR0MemObjSolLargePageFree(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
-                else
-                    rtR0SolMemFree(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
-            }
-            break;
-
-        case RTR0MEMOBJTYPE_PHYS_NC:
-            rtR0MemObjSolPagesFree(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
-            break;
-
-        case RTR0MEMOBJTYPE_PAGE:
-            ddi_umem_free(pMemSolaris->Cookie);
-            break;
-
-        case RTR0MEMOBJTYPE_LOCK:
-            rtR0MemObjSolUnlock(pMemSolaris->Core.pv, pMemSolaris->Core.cb, pMemSolaris->fAccess);
-            break;
-
-        case RTR0MEMOBJTYPE_MAPPING:
-            rtR0MemObjSolUnmap(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
-            break;
-
-        case RTR0MEMOBJTYPE_RES_VIRT:
-        {
-            if (pMemSolaris->Core.u.ResVirt.R0Process == NIL_RTR0PROCESS)
-                vmem_xfree(heap_arena, pMemSolaris->Core.pv, pMemSolaris->Core.cb);
-            else
-                AssertFailed();
-            break;
-        }
-
-        case RTR0MEMOBJTYPE_CONT: /* we don't use this type here. */
-        default:
-            AssertMsgFailed(("enmType=%d\n", pMemSolaris->Core.enmType));
-            return VERR_INTERNAL_ERROR;
-    }
-
-    return VINF_SUCCESS;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
-{
-    /* Create the object. */
-    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PAGE, NULL, cb);
-    if (RT_UNLIKELY(!pMemSolaris))
-        return VERR_NO_MEMORY;
-
-    void *pvMem = ddi_umem_alloc(cb, DDI_UMEM_SLEEP, &pMemSolaris->Cookie);
-    if (RT_UNLIKELY(!pvMem))
-    {
-        rtR0MemObjDelete(&pMemSolaris->Core);
-        return VERR_NO_PAGE_MEMORY;
-    }
-
-    pMemSolaris->Core.pv  = pvMem;
-    pMemSolaris->pvHandle = NULL;
-    *ppMem = &pMemSolaris->Core;
-    return VINF_SUCCESS;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
-{
-    NOREF(fExecutable);
-
-    /* Create the object */
-    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOW, NULL, cb);
-    if (!pMemSolaris)
-        return VERR_NO_MEMORY;
-
-    /* Allocate physically low page-aligned memory. */
-    uint64_t uPhysHi = _4G - 1;
-    void *pvMem = rtR0SolMemAlloc(uPhysHi, NULL /* puPhys */, cb, PAGESIZE, false /* fContig */);
-    if (RT_UNLIKELY(!pvMem))
-    {
-        rtR0MemObjDelete(&pMemSolaris->Core);
-        return VERR_NO_LOW_MEMORY;
-    }
-    pMemSolaris->Core.pv = pvMem;
-    pMemSolaris->pvHandle = NULL;
-    *ppMem = &pMemSolaris->Core;
-    return VINF_SUCCESS;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
-{
-    NOREF(fExecutable);
-    return rtR0MemObjNativeAllocPhys(ppMem, cb, _4G - 1, PAGE_SIZE /* alignment */);
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
-{
-#if HC_ARCH_BITS == 64
-    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS_NC, NULL, cb);
-    if (RT_UNLIKELY(!pMemSolaris))
-        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;
-
-#else /* 32 bit: */
-    return VERR_NOT_SUPPORTED; /* see the RTR0MemObjAllocPhysNC specs */
-#endif
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment)
-{
-    AssertMsgReturn(PhysHighest >= 16 *_1M, ("PhysHigest=%RHp\n", PhysHighest), VERR_NOT_SUPPORTED);
-
-    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS, NULL, cb);
-    if (RT_UNLIKELY(!pMemSolaris))
-        return VERR_NO_MEMORY;
-
-    /*
-     * Allocating one large page gets special treatment.
-     */
-    static uint32_t s_cbLargePage = UINT32_MAX;
-    if (s_cbLargePage == UINT32_MAX)
-    {
-#if 0 /* currently not entirely stable, so disabled. */
-        if (page_num_pagesizes() > 1)
-            ASMAtomicWriteU32(&s_cbLargePage, page_get_pagesize(1));
-        else
-#endif
-            ASMAtomicWriteU32(&s_cbLargePage, 0);
-    }
-    uint64_t PhysAddr;
-    if (   cb == s_cbLargePage
-        && cb == uAlignment
-        && PhysHighest == NIL_RTHCPHYS)
-    {
-        /*
-         * Allocate one large page.
-         */
-        void *pvPages = rtR0MemObjSolLargePageAlloc(&PhysAddr, cb);
-        if (RT_LIKELY(pvPages))
-        {
-            AssertMsg(!(PhysAddr & (cb - 1)), ("%RHp\n", PhysAddr));
-            pMemSolaris->Core.pv                = NULL;
-            pMemSolaris->Core.u.Phys.PhysBase   = PhysAddr;
-            pMemSolaris->Core.u.Phys.fAllocated = true;
-            pMemSolaris->pvHandle               = pvPages;
-            pMemSolaris->fLargePage             = true;
-
-            *ppMem = &pMemSolaris->Core;
-            return VINF_SUCCESS;
-        }
-    }
-    else
-    {
-        /*
-         * Allocate physically contiguous memory aligned as specified.
-         */
-        AssertCompile(NIL_RTHCPHYS == UINT64_MAX);
-        PhysAddr = PhysHighest;
-        void *pvMem = rtR0SolMemAlloc(PhysHighest, &PhysAddr, cb, uAlignment, true /* fContig */);
-        if (RT_LIKELY(pvMem))
-        {
-            Assert(!(PhysAddr & PAGE_OFFSET_MASK));
-            Assert(PhysAddr < PhysHighest);
-            Assert(PhysAddr + cb <= PhysHighest);
-
-            pMemSolaris->Core.pv                = pvMem;
-            pMemSolaris->Core.u.Phys.PhysBase   = PhysAddr;
-            pMemSolaris->Core.u.Phys.fAllocated = true;
-            pMemSolaris->pvHandle               = NULL;
-            pMemSolaris->fLargePage             = false;
-
-            *ppMem = &pMemSolaris->Core;
-            return VINF_SUCCESS;
-        }
-    }
-    rtR0MemObjDelete(&pMemSolaris->Core);
-    return VERR_NO_CONT_MEMORY;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy)
-{
-    AssertReturn(uCachePolicy == RTMEM_CACHE_POLICY_DONT_CARE, VERR_NOT_SUPPORTED);
-
-    /* Create the object. */
-    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS, NULL, cb);
-    if (!pMemSolaris)
-        return VERR_NO_MEMORY;
-
-    /* There is no allocation here, it needs to be mapped somewhere first. */
-    pMemSolaris->Core.u.Phys.fAllocated   = false;
-    pMemSolaris->Core.u.Phys.PhysBase     = Phys;
-    pMemSolaris->Core.u.Phys.uCachePolicy = uCachePolicy;
-    *ppMem = &pMemSolaris->Core;
-    return VINF_SUCCESS;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess,
-                                         RTR0PROCESS R0Process)
-{
-    AssertReturn(R0Process == RTR0ProcHandleSelf(), VERR_INVALID_PARAMETER);
-    NOREF(fAccess);
-
-    /* Create the locking object */
-    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb);
-    if (!pMemSolaris)
-        return VERR_NO_MEMORY;
-
-    /* Lock down user pages. */
-    int fPageAccess = S_READ;
-    if (fAccess & RTMEM_PROT_WRITE)
-        fPageAccess = S_WRITE;
-    if (fAccess & RTMEM_PROT_EXEC)
-        fPageAccess = S_EXEC;
-    int rc = rtR0MemObjSolLock((void *)R3Ptr, cb, fPageAccess);
-    if (RT_FAILURE(rc))
-    {
-        LogRel(("rtR0MemObjNativeLockUser: rtR0MemObjSolLock failed rc=%d\n", rc));
-        rtR0MemObjDelete(&pMemSolaris->Core);
-        return rc;
-    }
-
-    /* Fill in the object attributes and return successfully. */
-    pMemSolaris->Core.u.Lock.R0Process  = R0Process;
-    pMemSolaris->pvHandle               = NULL;
-    pMemSolaris->fAccess                = fPageAccess;
-    *ppMem = &pMemSolaris->Core;
-    return VINF_SUCCESS;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
-{
-    NOREF(fAccess);
-
-    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, pv, cb);
-    if (!pMemSolaris)
-        return VERR_NO_MEMORY;
-
-    /* Lock down kernel pages. */
-    int fPageAccess = S_READ;
-    if (fAccess & RTMEM_PROT_WRITE)
-        fPageAccess = S_WRITE;
-    if (fAccess & RTMEM_PROT_EXEC)
-        fPageAccess = S_EXEC;
-    int rc = rtR0MemObjSolLock(pv, cb, fPageAccess);
-    if (RT_FAILURE(rc))
-    {
-        LogRel(("rtR0MemObjNativeLockKernel: rtR0MemObjSolLock failed rc=%d\n", rc));
-        rtR0MemObjDelete(&pMemSolaris->Core);
-        return rc;
-    }
-
-    /* Fill in the object attributes and return successfully. */
-    pMemSolaris->Core.u.Lock.R0Process = NIL_RTR0PROCESS;
-    pMemSolaris->pvHandle              = NULL;
-    pMemSolaris->fAccess               = fPageAccess;
-    *ppMem = &pMemSolaris->Core;
-    return VINF_SUCCESS;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
-{
-    PRTR0MEMOBJSOL  pMemSolaris;
-
-    /*
-     * Use xalloc.
-     */
-    void *pv = vmem_xalloc(heap_arena, cb, uAlignment, 0 /* phase */, 0 /* nocross */,
-                           NULL /* minaddr */, NULL /* maxaddr */, VM_SLEEP);
-    if (RT_UNLIKELY(!pv))
-        return VERR_NO_MEMORY;
-
-    /* Create the object. */
-    pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_RES_VIRT, pv, cb);
-    if (!pMemSolaris)
-    {
-        LogRel(("rtR0MemObjNativeReserveKernel failed to alloc memory object.\n"));
-        vmem_xfree(heap_arena, pv, cb);
-        return VERR_NO_MEMORY;
-    }
-
-    pMemSolaris->Core.u.ResVirt.R0Process = NIL_RTR0PROCESS;
-    *ppMem = &pMemSolaris->Core;
-    return VINF_SUCCESS;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
-{
-    return VERR_NOT_SUPPORTED;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
-                                          unsigned fProt, size_t offSub, size_t cbSub)
-{
-    /** @todo rtR0MemObjNativeMapKernel / Solaris - Should be fairly simple alloc kernel memory and memload it. */
-    return VERR_NOT_SUPPORTED;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, PRTR0MEMOBJINTERNAL pMemToMap, RTR3PTR R3PtrFixed,
-                                        size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
-{
-    /*
-     * Fend off things we cannot do.
-     */
-    AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED);
-    AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
-    if (uAlignment != PAGE_SIZE)
-        return VERR_NOT_SUPPORTED;
-
-    /*
-     * Get parameters from the source object.
-     */
-    PRTR0MEMOBJSOL  pMemToMapSolaris     = (PRTR0MEMOBJSOL)pMemToMap;
-    void           *pv                   = pMemToMapSolaris->Core.pv;
-    size_t          cb                   = pMemToMapSolaris->Core.cb;
-    size_t          cPages               = cb >> PAGE_SHIFT;
-
-    /*
-     * Create the mapping object
-     */
-    PRTR0MEMOBJSOL pMemSolaris;
-    pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, cb);
-    if (RT_UNLIKELY(!pMemSolaris))
-        return VERR_NO_MEMORY;
-
-    int rc = VINF_SUCCESS;
-    uint64_t *paPhysAddrs = kmem_zalloc(sizeof(uint64_t) * cPages, KM_SLEEP);
-    if (RT_LIKELY(paPhysAddrs))
-    {
-        /*
-         * Prepare the pages according to type.
-         */
-        if (pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS_NC)
-            rc = rtR0MemObjSolPagesPreMap(pMemToMapSolaris->pvHandle, cb, paPhysAddrs, cPages);
-        else if (   pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS
-                 && pMemToMapSolaris->fLargePage)
-        {
-            RTHCPHYS Phys = pMemToMapSolaris->Core.u.Phys.PhysBase;
-            for (pgcnt_t iPage = 0; iPage < cPages; iPage++, Phys += PAGE_SIZE)
-                paPhysAddrs[iPage] = Phys;
-            rc = rtR0MemObjSolLargePagePreMap(pMemToMapSolaris->pvHandle, cb);
-        }
-        else
-        {
-            /*
-             * Have kernel mapping, just translate virtual to physical.
-             */
-            AssertPtr(pv);
-            rc = VINF_SUCCESS;
-            for (size_t iPage = 0; iPage < cPages; iPage++)
-            {
-                paPhysAddrs[iPage] = rtR0MemObjSolVirtToPhys(pv);
-                if (RT_UNLIKELY(paPhysAddrs[iPage] == -(uint64_t)1))
-                {
-                    LogRel(("rtR0MemObjNativeMapUser: no page to map.\n"));
-                    rc = VERR_MAP_FAILED;
-                    break;
-                }
-                pv = (void *)((uintptr_t)pv + PAGE_SIZE);
-            }
-        }
-        if (RT_SUCCESS(rc))
-        {
-            unsigned fPageAccess = PROT_READ;
-            if (fProt & RTMEM_PROT_WRITE)
-                fPageAccess |= PROT_WRITE;
-            if (fProt & RTMEM_PROT_EXEC)
-                fPageAccess |= PROT_EXEC;
-
-            /*
-             * Perform the actual mapping.
-             */
-            caddr_t UserAddr = NULL;
-            rc = rtR0MemObjSolUserMap(&UserAddr, fPageAccess, paPhysAddrs, cb);
-            if (RT_SUCCESS(rc))
-            {
-                pMemSolaris->Core.u.Mapping.R0Process = R0Process;
-                pMemSolaris->Core.pv                  = UserAddr;
-
-                *ppMem = &pMemSolaris->Core;
-                kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
-                return VINF_SUCCESS;
-            }
-
-            LogRel(("rtR0MemObjNativeMapUser: rtR0MemObjSolUserMap failed rc=%d.\n", rc));
-        }
-
-        rc = VERR_MAP_FAILED;
-        kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
-    }
-    else
-        rc = VERR_NO_MEMORY;
-    rtR0MemObjDelete(&pMemSolaris->Core);
-    return rc;
-}
-
-
-DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
-{
-    NOREF(pMem);
-    NOREF(offSub);
-    NOREF(cbSub);
-    NOREF(fProt);
-    return VERR_NOT_SUPPORTED;
-}
-
-
-DECLHIDDEN(RTHCPHYS) rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
-{
-    PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)pMem;
-
-    switch (pMemSolaris->Core.enmType)
-    {
-        case RTR0MEMOBJTYPE_PHYS_NC:
-            if (pMemSolaris->Core.u.Phys.fAllocated)
-            {
-                uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
-                return rtR0MemObjSolVirtToPhys(pb);
-            }
-            return rtR0MemObjSolPageToPhys(pMemSolaris->pvHandle, iPage);
-
-        case RTR0MEMOBJTYPE_PAGE:
-        case RTR0MEMOBJTYPE_LOW:
-        case RTR0MEMOBJTYPE_LOCK:
-        {
-            uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
-            return rtR0MemObjSolVirtToPhys(pb);
-        }
-
-        /*
-         * Although mapping can be handled by rtR0MemObjSolVirtToPhys(offset) like the above case,
-         * request it from the parent so that we have a clear distinction between CONT/PHYS_NC.
-         */
-        case RTR0MEMOBJTYPE_MAPPING:
-            return rtR0MemObjNativeGetPagePhysAddr(pMemSolaris->Core.uRel.Child.pParent, iPage);
-
-        case RTR0MEMOBJTYPE_CONT:
-        case RTR0MEMOBJTYPE_PHYS:
-            AssertFailed(); /* handled by the caller */
-        case RTR0MEMOBJTYPE_RES_VIRT:
-        default:
-            return NIL_RTHCPHYS;
-    }
-}
-
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/memobj-r0drv-solaris.h
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/memobj-r0drv-solaris.h	(revision 40967)
+++ 	(revision )
@@ -1,296 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - Ring-0 Memory Objects - Segment driver, Solaris.
- */
-
-/*
- * Copyright (C) 2012 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-#ifndef ___r0drv_solaris_memobj_r0drv_solaris_h
-#define ___r0drv_solaris_memobj_r0drv_solaris_h
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "../the-solaris-kernel.h"
-
-
-/*******************************************************************************
-*   Structures and Typedefs                                                    *
-*******************************************************************************/
-typedef struct SEGVBOX_CRARGS
-{
-    uint64_t *paPhysAddrs;
-    uint_t    fPageAccess;
-} SEGVBOX_CRARGS;
-typedef SEGVBOX_CRARGS *PSEGVBOX_CRARGS;
-
-typedef struct SEGVBOX_DATA
-{
-    uint_t    fPageAccess;
-} SEGVBOX_DATA;
-typedef SEGVBOX_DATA *PSEGVBOX_DATA;
-
-static struct seg_ops s_SegVBoxOps;
-static vnode_t s_segVBoxVnode;
-
-
-DECLINLINE(int) rtR0SegVBoxSolCreate(seg_t *pSeg, void *pvArgs)
-{
-    struct as      *pAddrSpace = pSeg->s_as;
-    PSEGVBOX_CRARGS pArgs      = pvArgs;
-    PSEGVBOX_DATA   pData      = kmem_zalloc(sizeof(*pData), KM_SLEEP);
-
-    AssertPtr(pAddrSpace);
-    AssertPtr(pArgs);
-    AssertPtr(pData);
-
-    hat_map(pAddrSpace->a_hat, pSeg->s_base, pSeg->s_size, HAT_MAP);
-    pData->fPageAccess = pArgs->fPageAccess | PROT_USER;
-
-    pSeg->s_ops  = &s_SegVBoxOps;
-    pSeg->s_data = pData;
-
-    /*
-     * Now load the locked mappings to the pages.
-     */
-    caddr_t virtAddr = pSeg->s_base;
-    pgcnt_t cPages   = (pSeg->s_size + PAGESIZE - 1) >> PAGESHIFT;
-    for (pgcnt_t iPage = 0; iPage < cPages; ++iPage, virtAddr += PAGESIZE)
-    {
-        hat_devload(pAddrSpace->a_hat, virtAddr, PAGESIZE, pArgs->paPhysAddrs[iPage] >> PAGESHIFT,
-                    pData->fPageAccess | HAT_UNORDERED_OK, HAT_LOAD | HAT_LOAD_LOCK);
-    }
-
-    return 0;
-}
-
-
-static int rtR0SegVBoxSolDup(seg_t *pSrcSeg, seg_t *pDstSeg)
-{
-    /*
-     * Duplicate a segment and return the new segment in 'pDstSeg'.
-     */
-    PSEGVBOX_DATA pSrcData = pSrcSeg->s_data;
-    PSEGVBOX_DATA pDstData = kmem_zalloc(sizeof(*pDstData), KM_SLEEP);
-
-    AssertPtr(pDstData);
-    AssertPtr(pSrcData);
-
-    pDstData->fPageAccess  = pSrcData->fPageAccess;
-    pDstSeg->s_ops         = &s_SegVBoxOps;
-    pDstSeg->s_data        = pDstData;
-
-    return 0;
-}
-
-
-static int rtR0SegVBoxSolUnmap(seg_t *pSeg, caddr_t virtAddr, size_t cb)
-{
-    /** @todo make these into release assertions. */
-    if (   virtAddr < pSeg->s_base
-        || virtAddr + cb > pSeg->s_base + pSeg->s_size
-        || (cb & PAGEOFFSET) || ((uintptr_t)virtAddr & PAGEOFFSET))
-    {
-        panic("rtRt0SegVBoxSolUnmap");
-    }
-
-    if (virtAddr != pSeg->s_base || cb != pSeg->s_size)
-        return ENOTSUP;
-
-    hat_unload(pSeg->s_as->a_hat, virtAddr, cb, HAT_UNLOAD_UNMAP | HAT_UNLOAD_UNLOCK);
-
-    seg_free(pSeg);
-    return 0;
-}
-
-
-static void rtR0SegVBoxSolFree(seg_t *pSeg)
-{
-    PSEGVBOX_DATA pData = pSeg->s_data;
-    kmem_free(pData, sizeof(*pData));
-}
-
-
-static int rtR0SegVBoxSolFault(struct hat *pHat, seg_t *pSeg, caddr_t virtAddr, size_t cb, enum fault_type FaultType,
-                               enum seg_rw ReadWrite)
-{
-    /*
-     * We would demand fault if the (u)read() path would SEGOP_FAULT() on buffers mapped in via our
-     * segment driver i.e. prefaults before DMA. Don't fail in such case where we're called directly,
-     * see #5047.
-     */
-    return 0;
-}
-
-
-static int rtR0SegVBoxSolFaultA(seg_t *pSeg, caddr_t virtAddr)
-{
-    return 0;
-}
-
-
-static int rtR0SegVBoxSolSetProt(seg_t *pSeg, caddr_t virtAddr, size_t cb, uint_t fPageAccess)
-{
-    return EACCES;
-}
-
-
-static int rtR0SegVBoxSolCheckProt(seg_t *pSeg, caddr_t virtAddr, size_t cb, uint_t fPageAccess)
-{
-    return EINVAL;
-}
-
-
-static int rtR0SegVBoxSolKluster(seg_t *pSeg, caddr_t virtAddr, ssize_t Delta)
-{
-    return -1;
-}
-
-
-static int rtR0SegVBoxSolSync(seg_t *pSeg, caddr_t virtAddr, size_t cb, int Attr, uint_t fFlags)
-{
-    return 0;
-}
-
-
-static size_t rtR0SegVBoxSolInCore(seg_t *pSeg, caddr_t virtAddr, size_t cb, char *pVec)
-{
-    size_t cbLen = (cb + PAGEOFFSET) & PAGEMASK;
-    for (virtAddr = 0; cbLen != 0; cbLen -= PAGESIZE, virtAddr += PAGESIZE)
-        *pVec++ = 1;
-    return cbLen;
-}
-
-
-static int rtR0SegVBoxSolLockOp(seg_t *pSeg, caddr_t virtAddr, size_t cb, int Attr, int Op, ulong_t *pLockMap, size_t off)
-{
-    return 0;
-}
-
-
-static int rtR0SegVBoxSolGetProt(seg_t *pSeg, caddr_t virtAddr, size_t cb, uint_t *pafPageAccess)
-{
-    PSEGVBOX_DATA pData = pSeg->s_data;
-    size_t iPage = seg_page(pSeg, virtAddr + cb) - seg_page(pSeg, virtAddr) + 1;
-    if (iPage)
-    {
-        do
-        {
-            iPage--;
-            pafPageAccess[iPage] = pData->fPageAccess;
-        } while (iPage);
-    }
-    return 0;
-}
-
-
-static u_offset_t rtR0SegVBoxSolGetOffset(seg_t *pSeg, caddr_t virtAddr)
-{
-    return ((uintptr_t)virtAddr - (uintptr_t)pSeg->s_base);
-}
-
-
-static int rtR0SegVBoxSolGetType(seg_t *pSeg, caddr_t virtAddr)
-{
-    return MAP_SHARED;
-}
-
-
-static int rtR0SegVBoxSolGetVp(seg_t *pSeg, caddr_t virtAddr, vnode_t **ppVnode)
-{
-    *ppVnode = &s_segVBoxVnode;
-    return 0;
-}
-
-
-static int rtR0SegVBoxSolAdvise(seg_t *pSeg, caddr_t virtAddr, size_t cb, uint_t Behav /* wut? */)
-{
-    return 0;
-}
-
-
-static void rtR0SegVBoxSolDump(seg_t *pSeg)
-{
-    /* Nothing to do. */
-}
-
-
-static int rtR0SegVBoxSolPageLock(seg_t *pSeg, caddr_t virtAddr, size_t cb, page_t ***pppPage, enum lock_type LockType, enum seg_rw ReadWrite)
-{
-    return ENOTSUP;
-}
-
-
-static int rtR0SegVBoxSolSetPageSize(seg_t *pSeg, caddr_t virtAddr, size_t cb, uint_t SizeCode)
-{
-    return ENOTSUP;
-}
-
-
-static int rtR0SegVBoxSolGetMemId(seg_t *pSeg, caddr_t virtAddr, memid_t *pMemId)
-{
-    return ENODEV;
-}
-
-
-static lgrp_mem_policy_info_t *rtR0SegVBoxSolGetPolicy(seg_t *pSeg, caddr_t virtAddr)
-{
-    return NULL;
-}
-
-
-static int rtR0SegVBoxSolCapable(seg_t *pSeg, segcapability_t Capab)
-{
-    return 0;
-}
-
-
-static struct seg_ops s_SegVBoxOps =
-{
-    rtR0SegVBoxSolDup,
-    rtR0SegVBoxSolUnmap,
-    rtR0SegVBoxSolFree,
-    rtR0SegVBoxSolFault,
-    rtR0SegVBoxSolFaultA,
-    rtR0SegVBoxSolSetProt,
-    rtR0SegVBoxSolCheckProt,
-    rtR0SegVBoxSolKluster,
-    NULL,                       /* swapout */
-    rtR0SegVBoxSolSync,
-    rtR0SegVBoxSolInCore,
-    rtR0SegVBoxSolLockOp,
-    rtR0SegVBoxSolGetProt,
-    rtR0SegVBoxSolGetOffset,
-    rtR0SegVBoxSolGetType,
-    rtR0SegVBoxSolGetVp,
-    rtR0SegVBoxSolAdvise,
-    rtR0SegVBoxSolDump,
-    rtR0SegVBoxSolPageLock,
-    rtR0SegVBoxSolSetPageSize,
-    rtR0SegVBoxSolGetMemId,
-    rtR0SegVBoxSolGetPolicy,
-    rtR0SegVBoxSolCapable
-};
-
-#endif /* ___r0drv_solaris_memobj_r0drv_solaris_h */
-
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/mp-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/mp-r0drv-solaris.c	(revision 40967)
+++ 	(revision )
@@ -1,346 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - Multiprocessor, Ring-0 Driver, Solaris.
- */
-
-/*
- * Copyright (C) 2008 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "../the-solaris-kernel.h"
-#include "internal/iprt.h"
-#include <iprt/mp.h>
-#include <iprt/cpuset.h>
-#include <iprt/thread.h>
-
-#include <iprt/asm.h>
-#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
-# include <iprt/asm-amd64-x86.h>
-#endif
-#include <iprt/err.h>
-#include "r0drv/mp-r0drv.h"
-
-typedef int FNRTMPSOLWORKER(void *pvUser1, void *pvUser2, void *pvUser3);
-typedef FNRTMPSOLWORKER *PFNRTMPSOLWORKER;
-
-
-RTDECL(bool) RTMpIsCpuWorkPending(void)
-{
-    return false;
-}
-
-
-RTDECL(RTCPUID) RTMpCpuId(void)
-{
-    return CPU->cpu_id;
-}
-
-
-RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
-{
-    return idCpu < RTCPUSET_MAX_CPUS && idCpu <= max_cpuid ? idCpu : -1;
-}
-
-
-RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
-{
-    return (unsigned)iCpu <= max_cpuid ? iCpu : NIL_RTCPUID;
-}
-
-
-RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
-{
-    return max_cpuid;
-}
-
-
-RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
-{
-    /*
-     * We cannot query CPU status recursively, check cpu member from cached set.
-     */
-    if (idCpu >= ncpus)
-        return false;
-
-    return RTCpuSetIsMember(&g_rtMpSolCpuSet, idCpu);
-}
-
-
-RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
-{
-    return idCpu < ncpus;
-}
-
-
-RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
-{
-    RTCPUID idCpu;
-
-    RTCpuSetEmpty(pSet);
-    idCpu = RTMpGetMaxCpuId(); /* it's inclusive */
-    do
-    {
-        if (RTMpIsCpuPossible(idCpu))
-            RTCpuSetAdd(pSet, idCpu);
-    } while (idCpu-- > 0);
-
-    return pSet;
-}
-
-
-RTDECL(RTCPUID) RTMpGetCount(void)
-{
-    return ncpus;
-}
-
-
-RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
-{
-    /*
-     * We cannot query CPU status recursively, return the cached set.
-     */
-    *pSet = g_rtMpSolCpuSet;
-    return pSet;
-}
-
-
-RTDECL(RTCPUID) RTMpGetOnlineCount(void)
-{
-    RTCPUSET Set;
-    RTMpGetOnlineSet(&Set);
-    return RTCpuSetCount(&Set);
-}
-
-
-/**
- * Wrapper to Solaris IPI infrastructure.
- *
- * @param    pCpuSet        Pointer to Solaris CPU set.
- * @param    pfnSolWorker     Function to execute on target CPU(s).
- * @param     pArgs            Pointer to RTMPARGS to pass to @a pfnSolWorker.
- *
- * @returns Solaris error code.
- */
-static void rtMpSolCrossCall(PRTSOLCPUSET pCpuSet, PFNRTMPSOLWORKER pfnSolWorker, PRTMPARGS pArgs)
-{
-    AssertPtrReturnVoid(pCpuSet);
-    AssertPtrReturnVoid(pfnSolWorker);
-    AssertPtrReturnVoid(pCpuSet);
-
-    if (g_frtSolOldIPI)
-    {
-        if (g_frtSolOldIPIUlong)
-        {
-            g_rtSolXcCall.u.pfnSol_xc_call_old_ulong((xc_arg_t)pArgs,          /* Arg to IPI function */
-                                                     0,                        /* Arg2, ignored */
-                                                     0,                        /* Arg3, ignored */
-                                                     IPRT_SOL_X_CALL_HIPRI,    /* IPI priority */
-                                                     pCpuSet->auCpus[0],       /* Target CPU(s) */
-                                                     (xc_func_t)pfnSolWorker); /* Function to execute on target(s) */
-        }
-        else
-        {
-            g_rtSolXcCall.u.pfnSol_xc_call_old((xc_arg_t)pArgs,          /* Arg to IPI function */
-                                               0,                        /* Arg2, ignored */
-                                               0,                        /* Arg3, ignored */
-                                               IPRT_SOL_X_CALL_HIPRI,    /* IPI priority */
-                                               *pCpuSet,                 /* Target CPU set */
-                                               (xc_func_t)pfnSolWorker); /* Function to execute on target(s) */
-        }
-    }
-    else
-    {
-        g_rtSolXcCall.u.pfnSol_xc_call((xc_arg_t)pArgs,          /* Arg to IPI function */
-                                       0,                        /* Arg2 */
-                                       0,                        /* Arg3 */
-                                       &pCpuSet->auCpus[0],      /* Target CPU set */
-                                       (xc_func_t)pfnSolWorker); /* Function to execute on target(s) */
-    }
-}
-
-
-/**
- * Wrapper between the native solaris per-cpu callback and PFNRTWORKER
- * for the RTMpOnAll API.
- *
- * @param   uArgs       Pointer to the RTMPARGS package.
- * @param   uIgnored1   Ignored.
- * @param   uIgnored2   Ignored.
- */
-static int rtMpSolOnAllCpuWrapper(void *uArg, void *uIgnored1, void *uIgnored2)
-{
-    PRTMPARGS pArgs = (PRTMPARGS)(uArg);
-
-    /*
-     * Solaris CPU cross calls execute on offline CPUs too. Check our CPU cache
-     * set and ignore if it's offline.
-     */
-    if (!RTMpIsCpuOnline(RTMpCpuId()))
-        return 0;
-
-    pArgs->pfnWorker(RTMpCpuId(), pArgs->pvUser1, pArgs->pvUser2);
-
-    NOREF(uIgnored1);
-    NOREF(uIgnored2);
-    return 0;
-}
-
-
-RTDECL(int) RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
-{
-    RTMPARGS Args;
-    RT_ASSERT_INTS_ON();
-
-    Args.pfnWorker = pfnWorker;
-    Args.pvUser1 = pvUser1;
-    Args.pvUser2 = pvUser2;
-    Args.idCpu = NIL_RTCPUID;
-    Args.cHits = 0;
-
-    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
-    RTThreadPreemptDisable(&PreemptState);
-
-    RTSOLCPUSET CpuSet;
-    for (int i = 0; i < IPRT_SOL_SET_WORDS; i++)
-        CpuSet.auCpus[i] = (ulong_t)-1L;
-
-    rtMpSolCrossCall(&CpuSet, rtMpSolOnAllCpuWrapper, &Args);
-
-    RTThreadPreemptRestore(&PreemptState);
-
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Wrapper between the native solaris per-cpu callback and PFNRTWORKER
- * for the RTMpOnOthers API.
- *
- * @param   uArgs       Pointer to the RTMPARGS package.
- * @param   uIgnored1   Ignored.
- * @param   uIgnored2   Ignored.
- */
-static int rtMpSolOnOtherCpusWrapper(void *uArg, void *uIgnored1, void *uIgnored2)
-{
-    PRTMPARGS pArgs = (PRTMPARGS)(uArg);
-    RTCPUID idCpu = RTMpCpuId();
-
-    Assert(idCpu != pArgs->idCpu);
-    pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
-
-    NOREF(uIgnored1);
-    NOREF(uIgnored2);
-    return 0;
-}
-
-
-RTDECL(int) RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
-{
-    RTMPARGS Args;
-    RT_ASSERT_INTS_ON();
-
-    Args.pfnWorker = pfnWorker;
-    Args.pvUser1 = pvUser1;
-    Args.pvUser2 = pvUser2;
-    Args.idCpu = RTMpCpuId();
-    Args.cHits = 0;
-
-    /* The caller is supposed to have disabled preemption, but take no chances. */
-    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
-    RTThreadPreemptDisable(&PreemptState);
-
-    RTSOLCPUSET CpuSet;
-    for (int i = 0; i < IPRT_SOL_SET_WORDS; i++)
-        CpuSet.auCpus[0] = (ulong_t)-1L;
-    BT_CLEAR(CpuSet.auCpus, RTMpCpuId());
-
-    rtMpSolCrossCall(&CpuSet, rtMpSolOnOtherCpusWrapper, &Args);
-
-    RTThreadPreemptRestore(&PreemptState);
-
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Wrapper between the native solaris per-cpu callback and PFNRTWORKER
- * for the RTMpOnSpecific API.
- *
- * @param   uArgs       Pointer to the RTMPARGS package.
- * @param   uIgnored1   Ignored.
- * @param   uIgnored2   Ignored.
- *
- * @returns Solaris error code.
- */
-static int rtMpSolOnSpecificCpuWrapper(void *uArg, void *uIgnored1, void *uIgnored2)
-{
-    PRTMPARGS pArgs = (PRTMPARGS)(uArg);
-    RTCPUID idCpu = RTMpCpuId();
-
-    Assert(idCpu == pArgs->idCpu);
-    pArgs->pfnWorker(idCpu, pArgs->pvUser1, pArgs->pvUser2);
-    ASMAtomicIncU32(&pArgs->cHits);
-
-    NOREF(uIgnored1);
-    NOREF(uIgnored2);
-    return 0;
-}
-
-
-RTDECL(int) RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2)
-{
-    RTMPARGS Args;
-    RT_ASSERT_INTS_ON();
-
-    if (idCpu >= ncpus)
-        return VERR_CPU_NOT_FOUND;
-
-    if (RT_UNLIKELY(!RTMpIsCpuOnline(idCpu)))
-        return RTMpIsCpuPresent(idCpu) ? VERR_CPU_OFFLINE : VERR_CPU_NOT_FOUND;
-
-    Args.pfnWorker = pfnWorker;
-    Args.pvUser1 = pvUser1;
-    Args.pvUser2 = pvUser2;
-    Args.idCpu = idCpu;
-    Args.cHits = 0;
-
-    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
-    RTThreadPreemptDisable(&PreemptState);
-
-    RTSOLCPUSET CpuSet;
-    for (int i = 0; i < IPRT_SOL_SET_WORDS; i++)
-        CpuSet.auCpus[i] = 0;
-    BT_SET(CpuSet.auCpus, idCpu);
-
-    rtMpSolCrossCall(&CpuSet, rtMpSolOnSpecificCpuWrapper, &Args);
-
-    RTThreadPreemptRestore(&PreemptState);
-
-    Assert(ASMAtomicUoReadU32(&Args.cHits) <= 1);
-
-    return ASMAtomicUoReadU32(&Args.cHits) == 1
-         ? VINF_SUCCESS
-         : VERR_CPU_NOT_FOUND;
-}
-
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/mpnotification-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/mpnotification-r0drv-solaris.c	(revision 40967)
+++ 	(revision )
@@ -1,187 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - Multiprocessor Event Notifications, Ring-0 Driver, Solaris.
- */
-
-/*
- * Copyright (C) 2008 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "../the-solaris-kernel.h"
-#include "internal/iprt.h"
-
-#include <iprt/err.h>
-#include <iprt/mp.h>
-#include <iprt/cpuset.h>
-#include <iprt/string.h>
-#include <iprt/thread.h>
-#include "r0drv/mp-r0drv.h"
-
-
-/*******************************************************************************
-*   Global Variables                                                           *
-*******************************************************************************/
-/** Whether CPUs are being watched or not. */
-static volatile bool g_fSolCpuWatch = false;
-/** Set of online cpus that is maintained by the MP callback.
- * This avoids locking issues querying the set from the kernel as well as
- * eliminating any uncertainty regarding the online status during the
- * callback. */
-RTCPUSET g_rtMpSolCpuSet;
-
-/**
- * Internal solaris representation for watching CPUs.
- */
-typedef struct RTMPSOLWATCHCPUS
-{
-    /** Function pointer to Mp worker. */
-    PFNRTMPWORKER   pfnWorker;
-    /** Argument to pass to the Mp worker. */
-    void           *pvArg;
-} RTMPSOLWATCHCPUS;
-typedef RTMPSOLWATCHCPUS *PRTMPSOLWATCHCPUS;
-
-
-/**
- * PFNRTMPWORKER worker for executing Mp events on the target CPU.
- *
- * @param    idCpu          The current CPU Id.
- * @param    pvArg          Opaque pointer to event type (online/offline).
- * @param    pvIgnored1     Ignored.
- */
-static void rtMpNotificationSolOnCurrentCpu(RTCPUID idCpu, void *pvArg, void *pvIgnored1)
-{
-    NOREF(pvIgnored1);
-    NOREF(idCpu);
-
-    PRTMPARGS pArgs = (PRTMPARGS)pvArg;
-    AssertRelease(pArgs && pArgs->idCpu == RTMpCpuId());
-    Assert(pArgs->pvUser1);
-    Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
-
-    RTMPEVENT enmMpEvent = *(RTMPEVENT *)pArgs->pvUser1;
-    rtMpNotificationDoCallbacks(enmMpEvent, pArgs->idCpu);
-}
-
-
-/**
- * Solaris callback function for Mp event notification.
- *
- * @param    CpuState   The current event/state of the CPU.
- * @param    iCpu       Which CPU is this event fore.
- * @param    pvArg      Ignored.
- *
- * @remarks This function assumes index == RTCPUID.
- * @returns Solaris error code.
- */
-static int rtMpNotificationCpuEvent(cpu_setup_t CpuState, int iCpu, void *pvArg)
-{
-    RTMPEVENT enmMpEvent;
-
-    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
-    RTThreadPreemptDisable(&PreemptState);
-
-    /*
-     * Update our CPU set structures first regardless of whether we've been
-     * scheduled on the right CPU or not, this is just atomic accounting.
-     */
-    if (CpuState == CPU_ON)
-    {
-        enmMpEvent = RTMPEVENT_ONLINE;
-        RTCpuSetAdd(&g_rtMpSolCpuSet, iCpu);
-    }
-    else if (CpuState == CPU_OFF)
-    {
-        enmMpEvent = RTMPEVENT_OFFLINE;
-        RTCpuSetDel(&g_rtMpSolCpuSet, iCpu);
-    }
-    else
-        return 0;
-
-    /*
-     * Since we don't absolutely need to do CPU bound code in any of the CPU offline
-     * notification hooks, run it on the current CPU. Scheduling a callback to execute
-     * on the CPU going offline at this point is too late and will not work reliably.
-     */
-    bool fRunningOnTargetCpu = iCpu == RTMpCpuId();
-    if (   fRunningOnTargetCpu == true
-        || enmMpEvent == RTMPEVENT_OFFLINE)
-    {
-        rtMpNotificationDoCallbacks(enmMpEvent, iCpu);
-    }
-    else
-    {
-        /*
-         * We're not on the target CPU, schedule (synchronous) the event notification callback
-         * to run on the target CPU i.e. the CPU that was online'd.
-         */
-        RTMPARGS Args;
-        RT_ZERO(Args);
-        Args.pvUser1 = &enmMpEvent;
-        Args.pvUser2 = NULL;
-        Args.idCpu   = iCpu;
-        RTMpOnSpecific(iCpu, rtMpNotificationSolOnCurrentCpu, &Args, NULL /* pvIgnored1 */);
-    }
-
-    RTThreadPreemptRestore(&PreemptState);
-
-    NOREF(pvArg);
-    return 0;
-}
-
-
-DECLHIDDEN(int) rtR0MpNotificationNativeInit(void)
-{
-    if (ASMAtomicReadBool(&g_fSolCpuWatch) == true)
-        return VERR_WRONG_ORDER;
-
-    /*
-     * Register the callback building the online cpu set as we do so.
-     */
-    RTCpuSetEmpty(&g_rtMpSolCpuSet);
-
-    mutex_enter(&cpu_lock);
-    register_cpu_setup_func(rtMpNotificationCpuEvent, NULL /* pvArg */);
-
-    for (int i = 0; i < (int)RTMpGetCount(); ++i)
-        if (cpu_is_online(cpu[i]))
-            rtMpNotificationCpuEvent(CPU_ON, i, NULL /* pvArg */);
-
-    ASMAtomicWriteBool(&g_fSolCpuWatch, true);
-    mutex_exit(&cpu_lock);
-
-    return VINF_SUCCESS;
-}
-
-
-DECLHIDDEN(void) rtR0MpNotificationNativeTerm(void)
-{
-    if (ASMAtomicReadBool(&g_fSolCpuWatch) == true)
-    {
-        mutex_enter(&cpu_lock);
-        unregister_cpu_setup_func(rtMpNotificationCpuEvent, NULL /* pvArg */);
-        ASMAtomicWriteBool(&g_fSolCpuWatch, false);
-        mutex_exit(&cpu_lock);
-    }
-}
-
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/process-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/process-r0drv-solaris.c	(revision 40967)
+++ 	(revision )
@@ -1,49 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - Process Management, Ring-0 Driver, Solaris.
- */
-
-/*
- * Copyright (C) 2006-2007 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "../the-solaris-kernel.h"
-#include "internal/iprt.h"
-#include <iprt/process.h>
-
-
-
-RTDECL(RTPROCESS) RTProcSelf(void)
-{
-    return ddi_get_pid();
-}
-
-
-RTR0DECL(RTR0PROCESS) RTR0ProcHandleSelf(void)
-{
-    proc_t *pProcess = NULL;
-    drv_getparm(UPROCP, &pProcess);
-    return (RTR0PROCESS)pProcess;
-}
-
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/thread-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/thread-r0drv-solaris.c	(revision 40967)
+++ 	(revision )
@@ -1,185 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - Threads, Ring-0 Driver, Solaris.
- */
-
-/*
- * Copyright (C) 2006-2009 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "../the-solaris-kernel.h"
-#include "internal/iprt.h"
-#include <iprt/thread.h>
-
-#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
-# include <iprt/asm-amd64-x86.h>
-#endif
-#include <iprt/assert.h>
-#include <iprt/err.h>
-#include <iprt/mp.h>
-
-#define SOL_THREAD_PREEMPT       (*((char *)curthread + g_offrtSolThreadPreempt))
-#define SOL_CPU_RUNRUN           (*((char *)CPU + g_offrtSolCpuPreempt))
-#define SOL_CPU_KPRUNRUN         (*((char *)CPU + g_offrtSolCpuForceKernelPreempt))
-
-RTDECL(RTNATIVETHREAD) RTThreadNativeSelf(void)
-{
-    return (RTNATIVETHREAD)curthread;
-}
-
-
-static int rtR0ThreadSolSleepCommon(RTMSINTERVAL cMillies)
-{
-    clock_t cTicks;
-    RT_ASSERT_PREEMPTIBLE();
-
-    if (!cMillies)
-    {
-        RTThreadYield();
-        return VINF_SUCCESS;
-    }
-
-    if (cMillies != RT_INDEFINITE_WAIT)
-        cTicks = drv_usectohz((clock_t)(cMillies * 1000L));
-    else
-        cTicks = 0;
-
-    delay(cTicks);
-    return VINF_SUCCESS;
-}
-
-
-RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies)
-{
-    return rtR0ThreadSolSleepCommon(cMillies);
-}
-
-
-RTDECL(int) RTThreadSleepNoLog(RTMSINTERVAL cMillies)
-{
-    return rtR0ThreadSolSleepCommon(cMillies);
-}
-
-
-RTDECL(bool) RTThreadYield(void)
-{
-    RT_ASSERT_PREEMPTIBLE();
-
-    RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
-    RTThreadPreemptDisable(&PreemptState);
-
-    char cThreadPreempt = SOL_THREAD_PREEMPT;
-    char cForcePreempt  = SOL_CPU_KPRUNRUN;
-    bool fWillYield = false;
-    Assert(cThreadPreempt >= 1);
-
-    /*
-     * If we are the last preemption enabler for this thread and if force
-     * preemption is set on the CPU, only then we are guaranteed to be preempted.
-     */
-    if (cThreadPreempt == 1 && cForcePreempt != 0)
-        fWillYield = true;
-
-    RTThreadPreemptRestore(&PreemptState);
-    return fWillYield;
-}
-
-
-RTDECL(bool) RTThreadPreemptIsEnabled(RTTHREAD hThread)
-{
-    Assert(hThread == NIL_RTTHREAD);
-    if (RT_UNLIKELY(g_frtSolInitDone == false))
-    {
-        cmn_err(CE_CONT, "!RTThreadPreemptIsEnabled called before RTR0Init!\n");
-        return true;
-    }
-
-    bool fThreadPreempt = false;
-    if (SOL_THREAD_PREEMPT == 0)
-        fThreadPreempt = true;
-
-    if (!fThreadPreempt)
-        return false;
-#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
-    if (!ASMIntAreEnabled())
-        return false;
-#endif
-    if (getpil() >= DISP_LEVEL)
-        return false;
-    return true;
-}
-
-
-RTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread)
-{
-    Assert(hThread == NIL_RTTHREAD);
-
-    char cPreempt      = SOL_CPU_RUNRUN;
-    char cForcePreempt = SOL_CPU_KPRUNRUN;
-    return (cPreempt != 0 || cForcePreempt != 0);
-}
-
-
-RTDECL(bool) RTThreadPreemptIsPendingTrusty(void)
-{
-    /* yes, RTThreadPreemptIsPending is reliable. */
-    return true;
-}
-
-
-RTDECL(bool) RTThreadPreemptIsPossible(void)
-{
-    /* yes, kernel preemption is possible. */
-    return true;
-}
-
-
-RTDECL(void) RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState)
-{
-    AssertPtr(pState);
-
-    SOL_THREAD_PREEMPT++;
-    Assert(SOL_THREAD_PREEMPT >= 1);
-
-    RT_ASSERT_PREEMPT_CPUID_DISABLE(pState);
-}
-
-
-RTDECL(void) RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState)
-{
-    AssertPtr(pState);
-    RT_ASSERT_PREEMPT_CPUID_RESTORE(pState);
-
-    Assert(SOL_THREAD_PREEMPT >= 1);
-    if (--SOL_THREAD_PREEMPT == 0 && SOL_CPU_RUNRUN != 0)
-        kpreempt(KPREEMPT_SYNC);
-}
-
-
-RTDECL(bool) RTThreadIsInInterrupt(RTTHREAD hThread)
-{
-    Assert(hThread == NIL_RTTHREAD);
-    return servicing_interrupt() ? true : false;
-}
-
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/thread2-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/thread2-r0drv-solaris.c	(revision 40967)
+++ 	(revision )
@@ -1,128 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - Threads (Part 2), Ring-0 Driver, Solaris.
- */
-
-/*
- * Copyright (C) 2006-2007 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "../the-solaris-kernel.h"
-#include "internal/iprt.h"
-#include <iprt/thread.h>
-#include <iprt/process.h>
-
-#include <iprt/assert.h>
-#include <iprt/err.h>
-#include "internal/thread.h"
-
-
-
-DECLHIDDEN(int) rtThreadNativeInit(void)
-{
-    return VINF_SUCCESS;
-}
-
-
-RTDECL(RTTHREAD) RTThreadSelf(void)
-{
-    return rtThreadGetByNative(RTThreadNativeSelf());
-}
-
-
-DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
-{
-    int iPriority;
-    switch (enmType)
-    {
-        case RTTHREADTYPE_INFREQUENT_POLLER:    iPriority = 60;             break;
-        case RTTHREADTYPE_EMULATION:            iPriority = 66;             break;
-        case RTTHREADTYPE_DEFAULT:              iPriority = 72;             break;
-        case RTTHREADTYPE_MSG_PUMP:             iPriority = 78;             break;
-        case RTTHREADTYPE_IO:                   iPriority = 84;             break;
-        case RTTHREADTYPE_TIMER:                iPriority = 99;             break;
-        default:
-            AssertMsgFailed(("enmType=%d\n", enmType));
-            return VERR_INVALID_PARAMETER;
-    }
-
-    kthread_t *pCurThread = curthread;
-    Assert(pCurThread);
-    thread_lock(pCurThread);
-    thread_change_pri(pCurThread, iPriority, 0);
-    thread_unlock(pCurThread);
-    return VINF_SUCCESS;
-}
-
-
-DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
-{
-    NOREF(pThread);
-    /* There is nothing special that needs doing here, but the
-       user really better know what he's cooking. */
-    return VINF_SUCCESS;
-}
-
-
-DECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread)
-{
-    NOREF(pThread);
-}
-
-
-/**
- * Native thread main function.
- *
- * @param   pvThreadInt     The thread structure.
- */
-static void rtThreadNativeMain(void *pvThreadInt)
-{
-    PRTTHREADINT pThreadInt = (PRTTHREADINT)pvThreadInt;
-
-    rtThreadMain(pThreadInt, RTThreadNativeSelf(), &pThreadInt->szName[0]);
-    thread_exit();
-}
-
-
-DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThreadInt, PRTNATIVETHREAD pNativeThread)
-{
-    RT_ASSERT_PREEMPTIBLE();
-    kthread_t *pThread = thread_create(NULL,                            /* Stack, use base */
-                                       0,                               /* Stack size */
-                                       rtThreadNativeMain,              /* Thread function */
-                                       pThreadInt,                      /* Function data */
-                                       sizeof(pThreadInt),              /* Data size */
-                                       (proc_t *)RTR0ProcHandleSelf(),  /* Process handle */
-                                       TS_RUN,                          /* Ready to run */
-                                       minclsyspri                      /* Priority */
-                                       );
-    if (RT_LIKELY(pThread))
-    {
-        *pNativeThread = (RTNATIVETHREAD)pThread;
-        return VINF_SUCCESS;
-    }
-
-    return VERR_OUT_OF_RESOURCES;
-}
-
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/time-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/time-r0drv-solaris.c	(revision 40967)
+++ 	(revision )
@@ -1,70 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - Time, Ring-0 Driver, Solaris.
- */
-
-/*
- * Copyright (C) 2006-2007 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#define RTTIME_INCL_TIMESPEC
-#include "../the-solaris-kernel.h"
-#include "internal/iprt.h"
-#include <iprt/time.h>
-
-
-RTDECL(uint64_t) RTTimeNanoTS(void)
-{
-    return (uint64_t)gethrtime();
-}
-
-
-RTDECL(uint64_t) RTTimeMilliTS(void)
-{
-    return RTTimeNanoTS() / 1000000;
-}
-
-
-RTDECL(uint64_t) RTTimeSystemNanoTS(void)
-{
-    return RTTimeNanoTS();
-}
-
-
-RTDECL(uint64_t) RTTimeSystemMilliTS(void)
-{
-    return RTTimeNanoTS() / 1000000;
-}
-
-
-RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime)
-{
-    timestruc_t TimeSpec;
-
-    mutex_enter(&tod_lock);
-    TimeSpec = tod_get();
-    mutex_exit(&tod_lock);
-    return RTTimeSpecSetNano(pTime, (uint64_t)TimeSpec.tv_sec * 1000000000 + TimeSpec.tv_nsec);
-}
-
Index: unk/src/VBox/Runtime/r0drv/solaris/vbi/timer-r0drv-solaris.c
===================================================================
--- /trunk/src/VBox/Runtime/r0drv/solaris/vbi/timer-r0drv-solaris.c	(revision 40967)
+++ 	(revision )
@@ -1,419 +1,0 @@
-/* $Id$ */
-/** @file
- * IPRT - Timer, Ring-0 Driver, Solaris.
- */
-
-/*
- * Copyright (C) 2006-2007 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*******************************************************************************
-*   Header Files                                                               *
-*******************************************************************************/
-#include "../the-solaris-kernel.h"
-#include "internal/iprt.h"
-#include <iprt/timer.h>
-
-#include <iprt/asm.h>
-#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
-# include <iprt/asm-amd64-x86.h>
-#endif
-#include <iprt/assert.h>
-#include <iprt/err.h>
-#include <iprt/mem.h>
-#include <iprt/mp.h>
-#include <iprt/spinlock.h>
-#include <iprt/time.h>
-#include <iprt/thread.h>
-#include "internal/magics.h"
-
-#define SOL_TIMER_ANY_CPU       (-1)
-
-/*******************************************************************************
-*   Structures and Typedefs                                                    *
-*******************************************************************************/
-/**
- * Single-CPU timer handle.
- */
-typedef struct RTR0SINGLETIMERSOL
-{
-    /** Cyclic handler. */
-    cyc_handler_t           hHandler;
-    /** Cyclic time and interval representation. */
-    cyc_time_t              hFireTime;
-    /** Timer ticks. */
-    uint64_t                u64Tick;
-} RTR0SINGLETIMERSOL;
-typedef RTR0SINGLETIMERSOL *PRTR0SINGLETIMERSOL;
-
-/**
- * Omni-CPU timer handle.
- */
-typedef struct RTR0OMNITIMERSOL
-{
-    /** Absolute timestamp of when the timer should fire next. */
-    uint64_t                u64When;
-    /** Array of timer ticks per CPU. Reinitialized when a CPU is online'd. */
-    uint64_t               *au64Ticks;
-} RTR0OMNITIMERSOL;
-typedef RTR0OMNITIMERSOL *PRTR0OMNITIMERSOL;
-
-/**
- * The internal representation of a Solaris timer handle.
- */
-typedef struct RTTIMER
-{
-    /** Magic.
-     * This is RTTIMER_MAGIC, but changes to something else before the timer
-     * is destroyed to indicate clearly that thread should exit. */
-    uint32_t volatile       u32Magic;
-    /** Flag indicating that the timer is suspended. */
-    uint8_t volatile        fSuspended;
-    /** Whether the timer must run on all CPUs or not. */
-    uint8_t                 fAllCpu;
-    /** Whether the timer must run on a specific CPU or not. */
-    uint8_t                 fSpecificCpu;
-    /** The CPU it must run on if fSpecificCpu is set. */
-    uint8_t                 iCpu;
-    /** The nano second interval for repeating timers. */
-    uint64_t                interval;
-    /** Cyclic timer Id. */
-    cyclic_id_t             hCyclicId;
-    /** @todo Make this a union unless we intend to support omni<=>single timers
-     *        conversions. */
-    /** Single-CPU timer handle. */
-    PRTR0SINGLETIMERSOL     pSingleTimer;
-    /** Omni-CPU timer handle. */
-    PRTR0OMNITIMERSOL       pOmniTimer;
-    /** The user callback. */
-    PFNRTTIMER              pfnTimer;
-    /** The argument for the user callback. */
-    void                   *pvUser;
-} RTTIMER;
-
-
-/*******************************************************************************
-*   Defined Constants And Macros                                               *
-*******************************************************************************/
-/** Validates that the timer is valid. */
-#define RTTIMER_ASSERT_VALID_RET(pTimer) \
-    do \
-    { \
-        AssertPtrReturn(pTimer, VERR_INVALID_HANDLE); \
-        AssertMsgReturn((pTimer)->u32Magic == RTTIMER_MAGIC, ("pTimer=%p u32Magic=%x expected %x\n", (pTimer), (pTimer)->u32Magic, RTTIMER_MAGIC), \
-            VERR_INVALID_HANDLE); \
-    } while (0)
-
-
-/**
- * Callback wrapper for Omni-CPU and single-CPU timers.
- *
- * @param    pvArg              Opaque pointer to the timer.
- *
- * @remarks This will be executed in interrupt context but only at the specified
- *          level i.e. CY_LOCK_LEVEL in our case. We -CANNOT- call into the
- *          cyclic subsystem here, neither should pfnTimer().
- */
-static void rtTimerSolCallbackWrapper(void *pvArg)
-{
-    PRTTIMER pTimer = (PRTTIMER)pvArg;
-    AssertPtrReturnVoid(pTimer);
-
-    if (pTimer->pSingleTimer)
-    {
-        uint64_t u64Tick = ++pTimer->pSingleTimer->u64Tick;
-        pTimer->pfnTimer(pTimer, pTimer->pvUser, u64Tick);
-    }
-    else if (pTimer->pOmniTimer)
-    {
-        uint64_t u64Tick = ++pTimer->pOmniTimer->au64Ticks[CPU->cpu_id];
-        pTimer->pfnTimer(pTimer, pTimer->pvUser, u64Tick);
-    }
-}
-
-
-/**
- * Omni-CPU cyclic online event. This is called before the omni cycle begins to
- * fire on the specified CPU.
- *
- * @param    pvArg              Opaque pointer to the timer.
- * @param    pCpu               Pointer to the CPU on which it will fire.
- * @param    pCyclicHandler     Pointer to a cyclic handler to add to the CPU
- *                              specified in @a pCpu.
- * @param    pCyclicTime        Pointer to the cyclic time and interval object.
- *
- * @remarks We -CANNOT- call back into the cyclic subsystem here, we can however
- *          block (sleep).
- */
-static void rtTimerSolOmniCpuOnline(void *pvArg, cpu_t *pCpu, cyc_handler_t *pCyclicHandler, cyc_time_t *pCyclicTime)
-{
-    PRTTIMER pTimer = (PRTTIMER)pvArg;
-    AssertPtrReturnVoid(pTimer);
-    AssertPtrReturnVoid(pCpu);
-    AssertPtrReturnVoid(pCyclicHandler);
-    AssertPtrReturnVoid(pCyclicTime);
-
-    pTimer->pOmniTimer->au64Ticks[pCpu->cpu_id] = 0;
-    pCyclicHandler->cyh_func  = rtTimerSolCallbackWrapper;
-    pCyclicHandler->cyh_arg   = pTimer;
-    pCyclicHandler->cyh_level = CY_LOCK_LEVEL;
-
-    uint64_t u64Now = RTTimeNanoTS();
-    if (pTimer->pOmniTimer->u64When < u64Now)
-        pCyclicTime->cyt_when = u64Now + pTimer->interval / 2;
-    else
-        pCyclicTime->cyt_when = pTimer->pOmniTimer->u64When;
-
-    pCyclicTime->cyt_interval = pTimer->interval;
-}
-
-
-RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser)
-{
-    RT_ASSERT_PREEMPTIBLE();
-    *ppTimer = NULL;
-
-    /*
-     * Validate flags.
-     */
-    if (!RTTIMER_FLAGS_ARE_VALID(fFlags))
-        return VERR_INVALID_PARAMETER;
-
-    if (    (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC)
-        &&  (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL
-        &&  !RTMpIsCpuPossible(RTMpCpuIdFromSetIndex(fFlags & RTTIMER_FLAGS_CPU_MASK)))
-        return VERR_CPU_NOT_FOUND;
-
-    if ((fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL && u64NanoInterval == 0)
-        return VERR_NOT_SUPPORTED;
-
-    /*
-     * Allocate and initialize the timer handle.
-     */
-    PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer));
-    if (!pTimer)
-        return VERR_NO_MEMORY;
-
-    pTimer->u32Magic = RTTIMER_MAGIC;
-    pTimer->fSuspended = true;
-    if ((fFlags & RTTIMER_FLAGS_CPU_ALL) == RTTIMER_FLAGS_CPU_ALL)
-    {
-        pTimer->fAllCpu = true;
-        pTimer->fSpecificCpu = false;
-        pTimer->iCpu = 255;
-    }
-    else if (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC)
-    {
-        pTimer->fAllCpu = false;
-        pTimer->fSpecificCpu = true;
-        pTimer->iCpu = fFlags & RTTIMER_FLAGS_CPU_MASK; /* ASSUMES: index == cpuid */
-    }
-    else
-    {
-        pTimer->fAllCpu = false;
-        pTimer->fSpecificCpu = false;
-        pTimer->iCpu = 255;
-    }
-    pTimer->interval = u64NanoInterval;
-    pTimer->pfnTimer = pfnTimer;
-    pTimer->pvUser = pvUser;
-    pTimer->pSingleTimer = NULL;
-    pTimer->pOmniTimer = NULL;
-    pTimer->hCyclicId = CYCLIC_NONE;
-
-    cmn_err(CE_NOTE, "Create pTimer->u32Magic=%x RTTIMER_MAGIC=%x\n",  pTimer->u32Magic, RTTIMER_MAGIC);
-    *ppTimer = pTimer;
-    return VINF_SUCCESS;
-}
-
-
-RTDECL(int) RTTimerDestroy(PRTTIMER pTimer)
-{
-    if (pTimer == NULL)
-        return VINF_SUCCESS;
-    RTTIMER_ASSERT_VALID_RET(pTimer);
-    RT_ASSERT_INTS_ON();
-
-    /*
-     * Free the associated resources.
-     */
-    RTTimerStop(pTimer);
-    ASMAtomicWriteU32(&pTimer->u32Magic, ~RTTIMER_MAGIC);
-    RTMemFree(pTimer);
-    return VINF_SUCCESS;
-}
-
-
-RTDECL(int) RTTimerStart(PRTTIMER pTimer, uint64_t u64First)
-{
-    cmn_err(CE_NOTE, "Start pTimer->u32Magic=%x RTTIMER_MAGIC=%x\n",  pTimer->u32Magic, RTTIMER_MAGIC);
-    RTTIMER_ASSERT_VALID_RET(pTimer);
-    RT_ASSERT_INTS_ON();
-
-    if (!pTimer->fSuspended)
-        return VERR_TIMER_ACTIVE;
-
-    /* One-shot timers are not supported by the cyclic system. */
-    if (pTimer->interval == 0)
-        return VERR_NOT_SUPPORTED;
-
-    pTimer->fSuspended = false;
-    if (pTimer->fAllCpu)
-    {
-        PRTR0OMNITIMERSOL pOmniTimer = RTMemAllocZ(sizeof(RTR0OMNITIMERSOL));
-        if (RT_UNLIKELY(!pOmniTimer))
-            return VERR_NO_MEMORY;
-
-        pOmniTimer->au64Ticks = RTMemAllocZ(RTMpGetCount() * sizeof(uint64_t));
-        if (RT_UNLIKELY(!pOmniTimer->au64Ticks))
-        {
-            RTMemFree(pOmniTimer);
-            return VERR_NO_MEMORY;
-        }
-
-        /*
-         * Setup omni (all CPU) timer. The Omni-CPU online event will fire
-         * and from there we setup periodic timers per CPU.
-         */
-        pTimer->pOmniTimer = pOmniTimer;
-        pOmniTimer->u64When     = pTimer->interval + RTTimeNanoTS();
-
-        cyc_omni_handler_t hOmni;
-        hOmni.cyo_online        = rtTimerSolOmniCpuOnline;
-        hOmni.cyo_offline       = NULL;
-        hOmni.cyo_arg           = pTimer;
-
-        mutex_enter(&cpu_lock);
-        pTimer->hCyclicId = cyclic_add_omni(&hOmni);
-        mutex_exit(&cpu_lock);
-    }
-    else
-    {
-        int iCpu = SOL_TIMER_ANY_CPU;
-        if (pTimer->fSpecificCpu)
-        {
-            iCpu = pTimer->iCpu;
-            if (!RTMpIsCpuOnline(iCpu))    /* ASSUMES: index == cpuid */
-                return VERR_CPU_OFFLINE;
-        }
-
-        PRTR0SINGLETIMERSOL pSingleTimer = RTMemAllocZ(sizeof(RTR0SINGLETIMERSOL));
-        if (RT_UNLIKELY(!pSingleTimer))
-            return VERR_NO_MEMORY;
-
-        pTimer->pSingleTimer = pSingleTimer;
-        pSingleTimer->hHandler.cyh_func  = rtTimerSolCallbackWrapper;
-        pSingleTimer->hHandler.cyh_arg   = pTimer;
-        pSingleTimer->hHandler.cyh_level = CY_LOCK_LEVEL;
-
-        mutex_enter(&cpu_lock);
-        if (iCpu != SOL_TIMER_ANY_CPU && !cpu_is_online(cpu[iCpu]))
-        {
-            mutex_exit(&cpu_lock);
-            RTMemFree(pSingleTimer);
-            pTimer->pSingleTimer = NULL;
-            return VERR_CPU_OFFLINE;
-        }
-
-        pSingleTimer->hFireTime.cyt_when = u64First + RTTimeNanoTS();
-        if (pTimer->interval == 0)
-        {
-            /* @todo use gethrtime_max instead of LLONG_MAX? */
-            AssertCompileSize(pSingleTimer->hFireTime.cyt_interval, sizeof(long long));
-            pSingleTimer->hFireTime.cyt_interval = LLONG_MAX - pSingleTimer->hFireTime.cyt_when;
-        }
-        else
-            pSingleTimer->hFireTime.cyt_interval = pTimer->interval;
-
-        pTimer->hCyclicId = cyclic_add(&pSingleTimer->hHandler, &pSingleTimer->hFireTime);
-        if (iCpu != SOL_TIMER_ANY_CPU)
-            cyclic_bind(pTimer->hCyclicId, cpu[iCpu], NULL /* cpupart */);
-
-        mutex_exit(&cpu_lock);
-    }
-
-    return VINF_SUCCESS;
-}
-
-
-RTDECL(int) RTTimerStop(PRTTIMER pTimer)
-{
-    RTTIMER_ASSERT_VALID_RET(pTimer);
-    RT_ASSERT_INTS_ON();
-
-    if (pTimer->fSuspended)
-        return VERR_TIMER_SUSPENDED;
-
-    pTimer->fSuspended = true;
-    if (pTimer->pSingleTimer)
-    {
-        mutex_enter(&cpu_lock);
-        cyclic_remove(pTimer->hCyclicId);
-        mutex_exit(&cpu_lock);
-        RTMemFree(pTimer->pSingleTimer);
-    }
-    else if (pTimer->pOmniTimer)
-    {
-        mutex_enter(&cpu_lock);
-        cyclic_remove(pTimer->hCyclicId);
-        mutex_exit(&cpu_lock);
-        RTMemFree(pTimer->pOmniTimer->au64Ticks);
-        RTMemFree(pTimer->pOmniTimer);
-    }
-
-    return VINF_SUCCESS;
-}
-
-
-RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval)
-{
-    RTTIMER_ASSERT_VALID_RET(pTimer);
-
-    /** @todo implement me! */
-
-    return VERR_NOT_SUPPORTED;
-}
-
-
-RTDECL(uint32_t) RTTimerGetSystemGranularity(void)
-{
-    return nsec_per_tick;
-}
-
-
-RTDECL(int) RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted)
-{
-    return VERR_NOT_SUPPORTED;
-}
-
-
-RTDECL(int) RTTimerReleaseSystemGranularity(uint32_t u32Granted)
-{
-    return VERR_NOT_SUPPORTED;
-}
-
-
-RTDECL(bool) RTTimerCanDoHighResolution(void)
-{
-    /** @todo return true; - when missing bits have been implemented and tested*/
-    return false;
-}
-
