memobj-r0drv-freebsd.c revision ee6881e608d98c1ced98963aed047fc7644df794
/* $Id$ */
/** @file
* IPRT - Ring-0 Memory Objects, FreeBSD.
*/
/*
* Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
* Copyright (c) 2011 Andriy Gapon <avg@FreeBSD.org>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "the-freebsd-kernel.h"
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* The FreeBSD version of the memory object structure.
*/
typedef struct RTR0MEMOBJFREEBSD
{
/** The core structure. */
/** The VM object associated with the allocation. */
/**
* Gets the virtual memory map the specified object is mapped into.
*
* @returns VM map handle on success, NULL if no map.
* @param pMem The memory object.
*/
{
{
case RTR0MEMOBJTYPE_PAGE:
case RTR0MEMOBJTYPE_LOW:
case RTR0MEMOBJTYPE_CONT:
return kernel_map;
case RTR0MEMOBJTYPE_PHYS:
case RTR0MEMOBJTYPE_PHYS_NC:
return NULL; /* pretend these have no mapping atm. */
case RTR0MEMOBJTYPE_LOCK:
case RTR0MEMOBJTYPE_RES_VIRT:
case RTR0MEMOBJTYPE_MAPPING:
default:
return NULL;
}
}
{
int rc;
{
case RTR0MEMOBJTYPE_PAGE:
case RTR0MEMOBJTYPE_LOW:
case RTR0MEMOBJTYPE_CONT:
break;
case RTR0MEMOBJTYPE_LOCK:
{
break;
}
case RTR0MEMOBJTYPE_RES_VIRT:
{
break;
}
case RTR0MEMOBJTYPE_MAPPING:
{
break;
}
case RTR0MEMOBJTYPE_PHYS:
case RTR0MEMOBJTYPE_PHYS_NC:
{
{
vm_page_unwire(pPage, 0);
}
break;
}
default:
return VERR_INTERNAL_ERROR;
}
return VINF_SUCCESS;
}
{
int cTries = 0;
#if __FreeBSD_version > 1000000
if (fWire)
fFlags |= VM_ALLOC_WIRED;
while (cTries <= 1)
{
if (pPages)
break;
cTries++;
}
return pPages;
#else
while (cTries <= 1)
{
if (pPages)
break;
cTries++;
}
if (!pPages)
return pPages;
{
if (fWire)
{
}
}
return pPages;
#endif
}
{
if (fContiguous)
{
return VINF_SUCCESS;
return rcNoMem;
}
{
uAlignment, fWire);
if (!pPage)
{
/* Free all allocated pages */
while (iPage-- > 0)
{
if (fWire)
vm_page_unwire(pPage, 0);
}
return rcNoMem;
}
}
return VINF_SUCCESS;
}
{
int rc;
/* No additional object reference for auto-deallocation upon unmapping. */
if (rc == KERN_SUCCESS)
{
false, rcNoMem);
if (RT_SUCCESS(rc))
{
/* Store start address */
return VINF_SUCCESS;
}
}
else
{
}
return rc;
}
{
if (!pMemFreeBSD)
return VERR_NO_MEMORY;
int rc = rtR0MemObjFreeBSDAllocHelper(pMemFreeBSD, fExecutable, ~(vm_paddr_t)0, false, VERR_NO_MEMORY);
if (RT_FAILURE(rc))
{
return rc;
}
return rc;
}
{
if (!pMemFreeBSD)
return VERR_NO_MEMORY;
int rc = rtR0MemObjFreeBSDAllocHelper(pMemFreeBSD, fExecutable, _4G - 1, false, VERR_NO_LOW_MEMORY);
if (RT_FAILURE(rc))
{
return rc;
}
return rc;
}
{
if (!pMemFreeBSD)
return VERR_NO_MEMORY;
int rc = rtR0MemObjFreeBSDAllocHelper(pMemFreeBSD, fExecutable, _4G - 1, true, VERR_NO_CONT_MEMORY);
if (RT_FAILURE(rc))
{
return rc;
}
return rc;
}
bool fContiguous, int rcNoMem)
{
/* create the object. */
if (!pMemFreeBSD)
return VERR_NO_MEMORY;
if (PhysHighest != NIL_RTHCPHYS)
else
VmPhysAddrHigh = ~(vm_paddr_t)0;
if (RT_SUCCESS(rc))
{
if (fContiguous)
{
}
}
else
{
}
return rc;
}
DECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment)
{
return rtR0MemObjFreeBSDAllocPhysPages(ppMem, RTR0MEMOBJTYPE_PHYS, cb, PhysHighest, uAlignment, true, VERR_NO_MEMORY);
}
DECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
{
return rtR0MemObjFreeBSDAllocPhysPages(ppMem, RTR0MEMOBJTYPE_PHYS_NC, cb, PhysHighest, PAGE_SIZE, false, VERR_NO_PHYS_MEMORY);
}
DECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy)
{
/* create the object. */
PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD), RTR0MEMOBJTYPE_PHYS, NULL, cb);
if (!pMemFreeBSD)
return VERR_NO_MEMORY;
/* there is no allocation here, it needs to be mapped somewhere first. */
return VINF_SUCCESS;
}
/**
* Worker locking the memory in either kernel or user maps.
*/
{
int rc;
/* create the object. */
PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD), RTR0MEMOBJTYPE_LOCK, (void *)AddrStart, cb);
if (!pMemFreeBSD)
return VERR_NO_MEMORY;
/*
* We could've used vslock here, but we don't wish to be subject to
* resource usage restrictions, so we'll call vm_map_wire directly.
*/
AddrStart, /* start */
fFlags); /* flags */
if (rc == KERN_SUCCESS)
{
return VINF_SUCCESS;
}
return VERR_NO_MEMORY;/** @todo fix mach -> vbox error conversion for freebsd. */
}
DECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
{
return rtR0MemObjNativeLockInMap(ppMem,
cb,
}
DECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
{
return rtR0MemObjNativeLockInMap(ppMem,
cb,
}
/**
* Worker for the two virtual address space reservers.
*
* We're leaning on the examples provided by mmap and vm_mmap in vm_mmap.c here.
*/
static int rtR0MemObjNativeReserveInMap(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process, vm_map_t pMap)
{
int rc;
/*
* The pvFixed address range must be within the VM space when specified.
*/
if ( pvFixed != (void *)-1
return VERR_INVALID_PARAMETER;
/*
* Check that the specified alignment is supported.
*/
if (uAlignment > PAGE_SIZE)
return VERR_NOT_SUPPORTED;
/*
* Create the object.
*/
PRTR0MEMOBJFREEBSD pMemFreeBSD = (PRTR0MEMOBJFREEBSD)rtR0MemObjNew(sizeof(*pMemFreeBSD), RTR0MEMOBJTYPE_RES_VIRT, NULL, cb);
if (!pMemFreeBSD)
return VERR_NO_MEMORY;
: vm_map_min(pMap);
if (pvFixed != (void *)-1)
MapAddress + cb);
NULL, /* object */
0, /* offset */
&MapAddress, /* addr (IN/OUT) */
cb, /* length */
/* find_space */
VM_PROT_NONE, /* protection */
VM_PROT_ALL, /* max(_prot) ?? */
0); /* cow (copy-on-write) */
if (rc == KERN_SUCCESS)
{
if (R0Process != NIL_RTR0PROCESS)
{
MapAddress + cb,
}
return VINF_SUCCESS;
}
return rc;
}
DECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
{
}
DECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
{
}
DECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
{
// AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NOT_SUPPORTED);
/*
* Check that the specified alignment is supported.
*/
if (uAlignment > PAGE_SIZE)
return VERR_NOT_SUPPORTED;
int rc;
/* calc protection */
vm_prot_t ProtectionFlags = 0;
if (cbSub == 0)
offSub, /* Start offset in the object */
cbSub, /* Size of the mapping */
VMFS_ANY_SPACE, /* Whether a suitable address should be searched for first */
ProtectionFlags, /* protection flags */
VM_PROT_ALL, /* Maximum protection flags */
0); /* copy-on-write and similar flags */
if (rc == KERN_SUCCESS)
{
(void *)Addr,
cbSub);
if (pMemFreeBSD)
{
return VINF_SUCCESS;
}
}
else
return VERR_NO_MEMORY;
}
DECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
{
/*
* Check for unsupported stuff.
*/
AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
if (uAlignment > PAGE_SIZE)
return VERR_NOT_SUPPORTED;
int rc;
/* calc protection */
vm_prot_t ProtectionFlags = 0;
/* calc mapping address */
{
/** @todo: is this needed?. */
}
else
/* Insert the pObject in the map. */
0, /* Start offset in the object */
/* Whether a suitable address should be searched for first */
ProtectionFlags, /* protection flags */
VM_PROT_ALL, /* Maximum protection flags */
0); /* copy-on-write and similar flags */
if (rc == KERN_SUCCESS)
{
/*
* Create a mapping object for it.
*/
(void *)AddrR3,
if (pMemFreeBSD)
{
return VINF_SUCCESS;
}
}
else
return VERR_NO_MEMORY;
}
DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
{
vm_prot_t ProtectionFlags = 0;
if (!pVmMap)
return VERR_NOT_SUPPORTED;
if (krc == KERN_SUCCESS)
return VINF_SUCCESS;
return VERR_NOT_SUPPORTED;
}
{
{
case RTR0MEMOBJTYPE_LOCK:
{
{
/* later */
return NIL_RTHCPHYS;
}
}
case RTR0MEMOBJTYPE_MAPPING:
{
{
}
}
case RTR0MEMOBJTYPE_PAGE:
case RTR0MEMOBJTYPE_LOW:
case RTR0MEMOBJTYPE_PHYS_NC:
{
return addr;
}
case RTR0MEMOBJTYPE_PHYS:
case RTR0MEMOBJTYPE_CONT:
case RTR0MEMOBJTYPE_RES_VIRT:
default:
return NIL_RTHCPHYS;
}
}