diff options
Diffstat (limited to 'src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.h')
-rw-r--r-- | src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.h | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.h b/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.h new file mode 100644 index 00000000..5e8116cf --- /dev/null +++ b/src/VBox/Runtime/r0drv/solaris/memobj-r0drv-solaris.h @@ -0,0 +1,322 @@ +/* $Id: memobj-r0drv-solaris.h $ */ +/** @file + * IPRT - Ring-0 Memory Objects - Segment driver, Solaris. + */ + +/* + * Copyright (C) 2012-2020 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 IPRT_INCLUDED_SRC_r0drv_solaris_memobj_r0drv_solaris_h +#define IPRT_INCLUDED_SRC_r0drv_solaris_memobj_r0drv_solaris_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include "the-solaris-kernel.h" + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +typedef struct SEGVBOX_CRARGS +{ + uint64_t *paPhysAddrs; + size_t cbPageSize; + uint_t fPageAccess; +} SEGVBOX_CRARGS; +typedef SEGVBOX_CRARGS *PSEGVBOX_CRARGS; + +typedef struct SEGVBOX_DATA +{ + uint_t fPageAccess; + size_t cbPageSize; +} 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); + + /* + * Currently we only map _4K pages but this segment driver can handle any size + * supported by the Solaris HAT layer. + */ + size_t cbPageSize = pArgs->cbPageSize; + size_t uPageShift = 0; + switch (cbPageSize) + { + case _4K: uPageShift = 12; break; + case _2M: uPageShift = 21; break; + default: AssertReleaseMsgFailed(("Unsupported page size for mapping cbPageSize=%llx\n", cbPageSize)); break; + } + + hat_map(pAddrSpace->a_hat, pSeg->s_base, pSeg->s_size, HAT_MAP); + pData->fPageAccess = pArgs->fPageAccess | PROT_USER; + pData->cbPageSize = cbPageSize; + + pSeg->s_ops = &s_SegVBoxOps; + pSeg->s_data = pData; + + /* + * Now load and lock down the mappings to the physical addresses. + */ + caddr_t virtAddr = pSeg->s_base; + pgcnt_t cPages = (pSeg->s_size + cbPageSize - 1) >> uPageShift; + for (pgcnt_t iPage = 0; iPage < cPages; ++iPage, virtAddr += cbPageSize) + { + hat_devload(pAddrSpace->a_hat, virtAddr, cbPageSize, pArgs->paPhysAddrs[iPage] >> uPageShift, + pData->fPageAccess | HAT_UNORDERED_OK, 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; + pDstData->cbPageSize = pSrcData->cbPageSize; + pDstSeg->s_ops = &s_SegVBoxOps; + pDstSeg->s_data = pDstData; + + return 0; +} + + +static int rtR0SegVBoxSolUnmap(seg_t *pSeg, caddr_t virtAddr, size_t cb) +{ + PSEGVBOX_DATA pData = pSeg->s_data; + + AssertRelease(pData); + AssertReleaseMsg(virtAddr >= pSeg->s_base, ("virtAddr=%p s_base=%p\n", virtAddr, pSeg->s_base)); + AssertReleaseMsg(virtAddr + cb <= pSeg->s_base + pSeg->s_size, ("virtAddr=%p cb=%llu s_base=%p s_size=%llu\n", virtAddr, + cb, pSeg->s_base, pSeg->s_size)); + size_t cbPageOffset = pData->cbPageSize - 1; + AssertRelease(!(cb & cbPageOffset)); + AssertRelease(!((uintptr_t)virtAddr & cbPageOffset)); + + 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 @bugref{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) +{ + PSEGVBOX_DATA pData = pSeg->s_data; + AssertRelease(pData); + size_t uPageOffset = pData->cbPageSize - 1; + size_t uPageMask = ~uPageOffset; + size_t cbLen = (cb + uPageOffset) & uPageMask; + for (virtAddr = 0; cbLen != 0; cbLen -= pData->cbPageSize, virtAddr += pData->cbPageSize) + *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; +} + + +#if defined(VBOX_NEW_CRASH_DUMP_FORMAT) +static void rtR0SegVBoxSolDump(seg_t *pSeg, dump_addpage_f Func) +#else +static void rtR0SegVBoxSolDump(seg_t *pSeg) +#endif +{ + /* 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 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, + NULL, /* getpolicy() */ + rtR0SegVBoxSolCapable +}; + +#endif /* !IPRT_INCLUDED_SRC_r0drv_solaris_memobj_r0drv_solaris_h */ + |