memobj-r0drv-solaris.c revision fc1a542a5c7d0145cd55065dcc4c9abf1c692b89
adf2bcd2e5d07d5a11553b88e147c1f4b2249bffvboxsync * IPRT - Ring-0 Memory Objects, Solaris.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Copyright (C) 2006-2007 Oracle Corporation
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * available from http://www.virtualbox.org. This file is free software;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * you can redistribute it and/or modify it under the terms of the GNU
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * General Public License (GPL) as published by the Free Software
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * The contents of this file may alternatively be used under the terms
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * of the Common Development and Distribution License Version 1.0
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * VirtualBox OSE distribution, in which case the provisions of the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * CDDL are applicable instead of those of the GPL.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * You may elect to license modified versions of this file under the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * terms and conditions of either the GPL or the CDDL or both.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/*******************************************************************************
23179f1443b03947d85eccc81cbc6b5153a4abf3vboxsync* Header Files *
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync*******************************************************************************/
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#define SOL_IS_KRNL_ADDR(vx) ((uintptr_t)(vx) >= kernelbase)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/*******************************************************************************
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync* Structures and Typedefs *
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync*******************************************************************************/
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * The Solaris version of the memory object structure.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /** The core structure. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /** Pointer to kernel memory cookie. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** Shadow locked pages. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** Access during locking. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** Set if large pages are involved in an RTR0MEMOBJTYPE_PHYS
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * allocation. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Returns the physical address for a virtual address.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param pv The virtual address.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @returns The physical address corresponding to @a pv.
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync PageFrameNum = hat_getpfnum(pHat, (caddr_t)(uVirtAddr & PAGEMASK));
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync AssertReleaseMsg(PageFrameNum != PFN_INVALID, ("rtR0MemObjSolVirtToPhys failed. pv=%p\n", pv));
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync return (((uint64_t)PageFrameNum << PAGESHIFT) | (uVirtAddr & PAGEOFFSET));
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Returns the physical address for a page.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param pPage Pointer to the page.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @returns The physical address for a page.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsyncstatic inline uint64_t rtR0MemObjSolPagePhys(page_t *pPage)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync AssertReleaseMsg(PageFrameNum != PFN_INVALID, ("rtR0MemObjSolPagePhys failed pPage=%p\n"));
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Retreives a free page from the kernel freelist.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param virtAddr The virtual address to which this page maybe mapped in
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * the future.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param cbPage The size of the page.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @returns Pointer to the allocated page, NULL on failure.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsyncstatic page_t *rtR0MemObjSolPageFromFreelist(caddr_t virtAddr, size_t cbPage)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync page_t *pPage = page_get_freelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pPage = page_get_freelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Retrieves a free page from the kernel cachelist.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param virtAddr The virtual address to which this page maybe mapped in
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * the future.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param cbPage The size of the page.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @return Pointer to the allocated page, NULL on failure.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsyncstatic page_t *rtR0MemObjSolPageFromCachelist(caddr_t virtAddr, size_t cbPage)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync page_t *pPage = page_get_cachelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync pPage = page_get_cachelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Remove association with the vnode for pages from the cachelist.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Allocates physical non-contiguous memory.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param uPhysHi The upper physical address limit (inclusive).
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param puPhys Where to store the physical address of first page. Optional,
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * can be NULL.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param cb The size of the allocation.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @return Array of allocated pages, NULL on failure.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsyncstatic page_t **rtR0MemObjSolPagesAlloc(uint64_t uPhysHi, uint64_t *puPhys, size_t cb)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * The page freelist and cachelist both hold pages that are not mapped into any address space.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * The cachelist is not really free pages but when memory is exhausted they'll be moved to the
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * free lists, it's the total of the free+cache list that we see on the 'free' column in vmstat.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Reserve available memory for pages and create the pages.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Get pages from kseg, the 'virtAddr' here is only for colouring but unfortunately
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * we don't yet have the 'virtAddr' to which this memory may be mapped.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync for (size_t i = 0; i < cPages; i++, virtAddr += PAGESIZE)
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync * Get a page from the freelist or cachelist & verify if it's within our
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync * requested range.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pPage = rtR0MemObjSolPageFromFreelist(virtAddr, PAGESIZE);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pPage = rtR0MemObjSolPageFromCachelist(virtAddr, PAGESIZE);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync page_free(pPage, 0 /* don't need page, move to tail of pagelist */);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync * No pages found or found pages didn't meet requirements, release what was grabbed so far.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync while (--i >= 0)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_free(ppPages[i], 0 /* don't need page, move to tail of pagelist */);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync * We now have the pages locked exclusively, before they are mapped in
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * we must downgrade the lock.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Prepares pages allocated by rtR0MemObjSolPagesAlloc for mapping.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param ppPages Pointer to the page list.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param cb Size of the allocation.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param auPhys Where to store the physical address of the premapped
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param cPages The number of pages (entries) in @a auPhys.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @returns IPRT status code.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncstatic int rtR0MemObjSolPagesPreMap(page_t **ppPages, size_t cb, uint64_t auPhys[], size_t cPages)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Prepare pages for mapping into kernel/user-space. Downgrade the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * exclusive page lock to a shared lock to prevent page relocation.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync auPhys[iPage] = rtR0MemObjSolPagePhys(ppPages[iPage]);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Frees pages allocated by rtR0MemObjSolPagesAlloc.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param ppPages Pointer to the page list.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param cbPages Size of the allocation.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncstatic void rtR0MemObjSolPagesFree(page_t **ppPages, size_t cb)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * We need to exclusive lock the pages before freeing them.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync while (!page_lock(ppPages[iPage], SE_EXCL, NULL /* mutex */, P_RECLAIM))
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync /* nothing */;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_free(ppPages[iPage], 0 /* don't need page, move to tail of pagelist */);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Allocates a large page to cover the required allocation size.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param puPhys Where to store the physical address of the allocated
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * page. Optional, can be NULL.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param cb Size of the allocation.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @returns Pointer to the allocated large page, NULL on failure.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncstatic page_t *rtR0MemObjSolLargePageAlloc(uint64_t *puPhys, size_t cb)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Reserve available memory and create the sub-pages.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Get a page off the free list. We set virtAddr to 0 since we don't know where
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * the memory is going to be mapped.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_t *pRootPage = rtR0MemObjSolPageFromFreelist(virtAddr, cb);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync AssertMsg(!(page_pptonum(pRootPage) & (cPages - 1)), ("%p:%lx cPages=%lx\n", pRootPage, page_pptonum(pRootPage), cPages));
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync * Mark all the sub-pages as non-free and not-hashed-in.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * It is paramount that we destroy the list (before freeing it).
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync * Ensure page is now be free and the page size-code must match that of the root page.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync AssertMsg(pPage->p_szc == pRootPage->p_szc, ("%p - %d expected %d \n", pPage, pPage->p_szc, pRootPage->p_szc));
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync AssertMsg(!(uPhys & (cb - 1)), ("%llx %zx\n", uPhys, cb));
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Prepares the large page allocated by rtR0MemObjSolLargePageAlloc to be mapped.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param pRootPage Pointer to the root page.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param cb Size of the allocation.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @returns IPRT status code.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncstatic int rtR0MemObjSolLargePagePreMap(page_t *pRootPage, size_t cb)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync Assert(page_get_pagecnt(pRootPage->p_szc) == cPages);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync AssertMsg(!(page_pptonum(pRootPage) & (cPages - 1)), ("%p:%lx npages=%lx\n", pRootPage, page_pptonum(pRootPage), cPages));
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * We need to downgrade the sub-pages from exclusive to shared locking
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * to prevent page relocation.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Frees the page allocated by rtR0MemObjSolLargePageAlloc.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param pRootPage Pointer to the root page.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param cb Allocated size.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsyncstatic void rtR0MemObjSolLargePageFree(page_t *pRootPage, size_t cb)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync Assert(page_get_pagecnt(pRootPage->p_szc) == cPages);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertMsg(!(page_pptonum(pRootPage) & (cPages - 1)), ("%p:%lx cPages=%lx\n", pRootPage, page_pptonum(pRootPage), cPages));
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync * We need to exclusively lock the sub-pages before freeing the large one.
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync while (!page_lock(pPage, SE_EXCL, NULL /* mutex */, P_RECLAIM))
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync /* nothing */;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Free the large page and unreserve the memory.
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync * Unmaps kernel/user-space mapped memory.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param pv Pointer to the mapped memory block.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param cb Size of the memory block.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync hat_unload(kas.a_hat, pv, cb, HAT_UNLOAD | HAT_UNLOAD_UNLOCK);
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync struct as *pAddrSpace = ((proc_t *)RTR0ProcHandleSelf())->p_as;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Lock down memory mappings for a virtual address.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param pv Pointer to the memory to lock down.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param cb Size of the memory block.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param fAccess Page access rights (S_READ, S_WRITE, S_EXEC)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @returns IPRT status code.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncstatic int rtR0MemObjSolLock(void *pv, size_t cb, int fPageAccess)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Kernel memory mappings on x86/amd64 are always locked, only handle user-space memory.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync faultcode_t rc = as_fault(pProc->p_as->a_hat, pProc->p_as, (caddr_t)pv, cb, F_SOFTLOCK, fPageAccess);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync LogRel(("rtR0MemObjSolLock failed for pv=%pv cb=%lx fPageAccess=%d rc=%d\n", pv, cb, fPageAccess, rc));
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync * Unlock memory mappings for a virtual address.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param pv Pointer to the locked memory.
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync * @param cb Size of the memory block.
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync * @param fPageAccess Page access rights (S_READ, S_WRITE, S_EXEC).
91f8453d16b48876deddaba298c211071d0ca3a5vboxsyncstatic void rtR0MemObjSolUnlock(void *pv, size_t cb, int fPageAccess)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync as_fault(pProcess->p_as->a_hat, pProcess->p_as, (caddr_t)pv, cb, F_SOFTUNLOCK, fPageAccess);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Maps a list of physical pages into user address space.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param pVirtAddr Where to store the virtual address of the mapping.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param fPageAccess Page access rights (PROT_READ, PROT_WRITE,
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * PROT_EXEC)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param paPhysAddrs Array of physical addresses to pages.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param cb Size of memory being mapped.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @returns IPRT status code.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsyncstatic int rtR0MemObjSolUserMap(caddr_t *pVirtAddr, unsigned fPageAccess, uint64_t *paPhysAddrs, size_t cb)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync struct as *pAddrSpace = ((proc_t *)RTR0ProcHandleSelf())->p_as;
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync map_addr(pVirtAddr, cb, 0 /* offset */, 0 /* vacalign */, MAP_SHARED);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = as_map(pAddrSpace, *pVirtAddr, cb, rtR0SegVBoxSolCreate, &Args);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsyncDECLHIDDEN(int) rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0SolMemFree(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjSolLargePageFree(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync rtR0SolMemFree(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjSolPagesFree(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjSolUnlock(pMemSolaris->Core.pv, pMemSolaris->Core.cb, pMemSolaris->fAccess);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjSolUnmap(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (pMemSolaris->Core.u.ResVirt.R0Process == NIL_RTR0PROCESS)
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync vmem_xfree(heap_arena, pMemSolaris->Core.pv, pMemSolaris->Core.cb);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync case RTR0MEMOBJTYPE_CONT: /* we don't use this type here. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertMsgFailed(("enmType=%d\n", pMemSolaris->Core.enmType));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Create the object. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PAGE, NULL, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync void *pvMem = ddi_umem_alloc(cb, DDI_UMEM_SLEEP, &pMemSolaris->Cookie);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync /* Create the object */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOW, NULL, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Allocate physically low page-aligned memory. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync void *pvMem = rtR0SolMemAlloc(uPhysHi, NULL /* puPhys */, cb, PAGESIZE, false /* fContig */);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsyncDECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return rtR0MemObjNativeAllocPhys(ppMem, cb, _4G - 1, PAGE_SIZE /* alignment */);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS_NC, NULL, cb);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync void *pvPages = rtR0MemObjSolPagesAlloc((uint64_t)PhysHighest, &PhysAddr, cb);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync LogRel(("rtR0MemObjNativeAllocPhysNC: rtR0MemObjSolPagesAlloc failed for cb=%u.\n", cb));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#else /* 32 bit: */
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync return VERR_NOT_SUPPORTED; /* see the RTR0MemObjAllocPhysNC specs */
2823fbb1428e982169f04923472d7c94e7ed8385vboxsyncDECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertMsgReturn(PhysHighest >= 16 *_1M, ("PhysHigest=%RHp\n", PhysHighest), VERR_NOT_SUPPORTED);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS, NULL, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Allocating one large page gets special treatment.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#if 0 /* currently not entirely stable, so disabled. */
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync ASMAtomicWriteU32(&s_cbLargePage, page_get_pagesize(1));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Allocate one large page.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync void *pvPages = rtR0MemObjSolLargePageAlloc(&PhysAddr, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertMsg(!(PhysAddr & (cb - 1)), ("%RHp\n", PhysAddr));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Allocate physically contiguous memory aligned as specified.
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync void *pvMem = rtR0SolMemAlloc(PhysHighest, &PhysAddr, cb, uAlignment, true /* fContig */);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncDECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy)
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync AssertReturn(uCachePolicy == RTMEM_CACHE_POLICY_DONT_CARE, VERR_NOT_SUPPORTED);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync /* Create the object. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS, NULL, cb);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync /* There is no allocation here, it needs to be mapped somewhere first. */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pMemSolaris->Core.u.Phys.uCachePolicy = uCachePolicy;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess,
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertReturn(R0Process == RTR0ProcHandleSelf(), VERR_INVALID_PARAMETER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Create the locking object */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Lock down user pages. */
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync int rc = rtR0MemObjSolLock((void *)R3Ptr, cb, fPageAccess);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync LogRel(("rtR0MemObjNativeLockUser: rtR0MemObjSolLock failed rc=%d\n", rc));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Fill in the object attributes and return successfully. */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncDECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, pv, cb);
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync /* Lock down kernel pages. */
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync LogRel(("rtR0MemObjNativeLockKernel: rtR0MemObjSolLock failed rc=%d\n", rc));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /* Fill in the object attributes and return successfully. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.u.Lock.R0Process = NIL_RTR0PROCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Use xalloc.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync void *pv = vmem_xalloc(heap_arena, cb, uAlignment, 0 /* phase */, 0 /* nocross */,
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync /* Create the object. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_RES_VIRT, pv, cb);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync LogRel(("rtR0MemObjNativeReserveKernel failed to alloc memory object.\n"));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pMemSolaris->Core.u.ResVirt.R0Process = NIL_RTR0PROCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsyncDECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /** @todo rtR0MemObjNativeMapKernel / Solaris - Should be fairly simple alloc kernel memory and memload it. */
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsyncDECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, PRTR0MEMOBJINTERNAL pMemToMap, RTR3PTR R3PtrFixed,
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Fend off things we cannot do.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
e214bb78026c1d64078b34ca9504d3f5abbc52efvboxsync * Get parameters from the source object.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync PRTR0MEMOBJSOL pMemToMapSolaris = (PRTR0MEMOBJSOL)pMemToMap;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Create the mapping object
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync uint64_t *paPhysAddrs = kmem_zalloc(sizeof(uint64_t) * cPages, KM_SLEEP);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Prepare the pages according to type.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS_NC)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync rc = rtR0MemObjSolPagesPreMap(pMemToMapSolaris->pvHandle, cb, paPhysAddrs, cPages);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else if ( pMemToMapSolaris->Core.enmType == RTR0MEMOBJTYPE_PHYS
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTHCPHYS Phys = pMemToMapSolaris->Core.u.Phys.PhysBase;
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync for (pgcnt_t iPage = 0; iPage < cPages; iPage++, Phys += PAGE_SIZE)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync rc = rtR0MemObjSolLargePagePreMap(pMemToMapSolaris->pvHandle, cb);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Have kernel mapping, just translate virtual to physical.
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync if (RT_UNLIKELY(paPhysAddrs[iPage] == -(uint64_t)1))
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync LogRel(("rtR0MemObjNativeMapUser: no page to map.\n"));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Perform the actual mapping.
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync rc = rtR0MemObjSolUserMap(&UserAddr, fPageAccess, paPhysAddrs, cb);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync LogRel(("rtR0MemObjNativeMapUser: rtR0MemObjSolUserMap failed rc=%d.\n", rc));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncDECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsyncDECLHIDDEN(RTHCPHYS) rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Although mapping can be handled by rtR0MemObjSolVirtToPhys(offset) like the above case,
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync * request it from the parent so that we have a clear distinction between CONT/PHYS_NC.