memobj-r0drv-solaris.c revision 43d5e45fa237a3eebb3e624d67a0eaf21502c336
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync * IPRT - Ring-0 Memory Objects, Solaris.
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * available from http://www.virtualbox.org. This file is free software;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * you can redistribute it and/or modify it under the terms of the GNU
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * General Public License (GPL) as published by the Free Software
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * The contents of this file may alternatively be used under the terms
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * of the Common Development and Distribution License Version 1.0
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * VirtualBox OSE distribution, in which case the provisions of the
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * CDDL are applicable instead of those of the GPL.
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * You may elect to license modified versions of this file under the
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * terms and conditions of either the GPL or the CDDL or both.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync * additional information or have any questions.
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync/*******************************************************************************
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync* Header Files *
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync*******************************************************************************/
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync/*******************************************************************************
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync* Structures and Typedefs *
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync*******************************************************************************/
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * The Solaris version of the memory object structure.
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /** The core structure. */
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync /** Pointer to kernel memory cookie. */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /** Shadow locked pages. */
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * Used for supplying the solaris kernel info. about memory limits
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync * during contiguous allocations (i_ddi_mem_alloc)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync (uint64_t)0xffffffff, /* high limit (32-bit PA, 4G) */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync 1, /* scatter-gather list length (1 for contiguous) */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync 0 /* bus-specific flags */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsyncstatic uint64_t rtR0MemObjSolarisVirtToPhys(struct hat* hatSpace, caddr_t virtAddr)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* We could use paddr_t (more solaris-like) rather than uint64_t but paddr_t isn't defined for 64-bit */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync AssertMsgFailed(("rtR0MemObjSolarisVirtToPhys: hat_getpfnum for %p failed.\n", virtAddr));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Both works, but second will work for non-page aligned virtAddr */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync uint64_t physAddr = ((uint64_t)pfn << MMU_PAGESHIFT) | ((uintptr_t)virtAddr & MMU_PAGEOFFSET);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)pMem;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync if (pMemSolaris->Core.u.Lock.R0Process == NIL_RTR0PROCESS)
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync addrSpace = ((proc_t *)pMemSolaris->Core.u.Lock.R0Process)->p_as;
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync as_pageunlock(addrSpace, pMemSolaris->ppShadowPages, pMemSolaris->Core.pv, pMemSolaris->Core.cb, S_WRITE);
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync if (pMemSolaris->Core.u.Mapping.R0Process == NIL_RTR0PROCESS)
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync /* Kernel process*/
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* User process */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync proc_t *userProc = (proc_t *)pMemSolaris->Core.u.Mapping.R0Process;
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync hat_unload(hatSpace, pMemSolaris->Core.pv, pMemSolaris->Core.cb, HAT_UNLOAD_UNLOCK);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync as_unmap(addrSpace, pMemSolaris->Core.pv, pMemSolaris->Core.cb);
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync /* unused */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync AssertMsgFailed(("enmType=%d\n", pMemSolaris->Core.enmType));
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsyncint rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync /* Create the object */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PAGE, NULL, cb);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync void *virtAddr = ddi_umem_alloc(cb, DDI_UMEM_SLEEP, &pMemSolaris->Cookie);
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsyncint rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Try page alloc first */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync int rc = rtR0MemObjNativeAllocPage(ppMem, cb, fExecutable);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync while (iPage-- > 0)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync if (rtR0MemObjNativeGetPagePhysAddr(*ppMem, iPage) > (_4G - PAGE_SIZE))
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync /* Failed! Fall back to physical contiguous alloc */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync rc = rtR0MemObjNativeAllocCont(ppMem, cb, fExecutable);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsyncint rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Create the object */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_CONT, NULL, cb);
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync /* Allocate physically contiguous page-aligned memory. */
9148e7ca5f9ee1d467112d347bfb2de2b97254d2vboxsync int rc = i_ddi_mem_alloc(NULL, &g_SolarisX86PhysMemLimits, cb, 1, 0, NULL, &virtAddr, NULL, NULL);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync pMemSolaris->Core.u.Cont.Phys = rtR0MemObjSolarisVirtToPhys(kas.a_hat, virtAddr);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsyncint rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /** @todo rtR0MemObjNativeAllocPhysNC / solaris */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync return VERR_NOT_SUPPORTED; /* see the RTR0MemObjAllocPhysNC specs */
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsyncint rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync AssertMsgReturn(PhysHighest >= 16 *_1M, ("PhysHigest=%VHp\n", PhysHighest), VERR_NOT_IMPLEMENTED);
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync return rtR0MemObjNativeAllocCont(ppMem, cb, false);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsyncint rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Create the object */
6a30d0e9d748ecb8a0c62b4233a97fed255a8a4cvboxsync PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS, NULL, cb);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* There is no allocation here, it needs to be mapped somewhere first */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsyncint rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync AssertReturn(R0Process == RTR0ProcHandleSelf(), VERR_INVALID_PARAMETER);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Create the locking object */
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb);
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync /* Lock down user pages */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync int rc = as_pagelock(useras, &ppl, (caddr_t)R3Ptr, cb, S_WRITE);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync pMemSolaris->Core.u.Lock.R0Process = (RTR0PROCESS)userproc;
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync as_pageunlock(useras, ppl, (caddr_t)R3Ptr, cb, S_WRITE);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync cmn_err(CE_NOTE, "rtR0MemObjNativeLockUser: as_pagelock failed to get shadow pages\n");
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync cmn_err(CE_NOTE,"rtR0MemObjNativeLockUser: as_pagelock failed rc=%d\n", rc);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsyncint rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb)
32ded45b3caba42c8a2315a20bbfabb513fa54c1vboxsync /* Create the locking object */
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, pv, cb);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync caddr_t virtAddr = (caddr_t)((uintptr_t)pv & (uintptr_t)PAGEMASK);
dc23707aec4dc2ce2c6b6f51af21eef72bb8bf2evboxsync /* Lock down kernel pages */
if (rc != 0)
return VERR_LOCK_FAILED;
if (!ppl)
return VERR_LOCK_FAILED;
pMemSolaris->Core.u.Lock.R0Process = NIL_RTR0PROCESS; /* means kernel, see rtR0MemObjNativeFree() */
return VINF_SUCCESS;
int rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
return VERR_NOT_IMPLEMENTED;
int rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
return VERR_NOT_IMPLEMENTED;
int rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment, unsigned fProt)
int rc;
PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, size);
if (!pMemSolaris)
return VERR_NO_MEMORY;
return VERR_NO_MEMORY;
return VERR_MAP_FAILED;
if (rc != 0)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
int rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, PRTR0MEMOBJINTERNAL pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
int rc;
PRTR0MEMOBJSOLARIS pMemSolaris = (PRTR0MEMOBJSOLARIS)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, size);
if (!pMemSolaris)
return VERR_NO_MEMORY;
return VERR_INVALID_POINTER;
return VERR_MAP_FAILED;
return VERR_MAP_FAILED;
if (rc != 0)
return VERR_MAP_FAILED;
return VERR_NO_MEMORY;
return VINF_SUCCESS;
case RTR0MEMOBJTYPE_PAGE:
case RTR0MEMOBJTYPE_LOW:
case RTR0MEMOBJTYPE_MAPPING:
case RTR0MEMOBJTYPE_LOCK:
case RTR0MEMOBJTYPE_CONT:
case RTR0MEMOBJTYPE_PHYS:
case RTR0MEMOBJTYPE_PHYS_NC:
case RTR0MEMOBJTYPE_RES_VIRT:
return NIL_RTHCPHYS;