memobj-r0drv-solaris.c revision fc1a542a5c7d0145cd55065dcc4c9abf1c692b89
9ad572a3ac0fd3845a9abecfbf41e8db9b3a5cf0vboxsync/* $Id$ */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/** @file
adf2bcd2e5d07d5a11553b88e147c1f4b2249bffvboxsync * IPRT - Ring-0 Memory Objects, Solaris.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/*
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Copyright (C) 2006-2007 Oracle Corporation
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *
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 *
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 *
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 */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
70bb61ea2f96e80150e807529ce5df435607706bvboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/*******************************************************************************
23179f1443b03947d85eccc81cbc6b5153a4abf3vboxsync* Header Files *
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync*******************************************************************************/
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include "the-solaris-kernel.h"
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include "internal/iprt.h"
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/memobj.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/asm.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/assert.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/err.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/log.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/mem.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/param.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include <iprt/process.h>
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#include "internal/memobj.h"
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#include "memobj-r0drv-solaris.h"
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#define SOL_IS_KRNL_ADDR(vx) ((uintptr_t)(vx) >= kernelbase)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncstatic vnode_t s_PageVnode;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/*******************************************************************************
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync* Structures and Typedefs *
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync*******************************************************************************/
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync/**
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * The Solaris version of the memory object structure.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsynctypedef struct RTR0MEMOBJSOL
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync{
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /** The core structure. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync RTR0MEMOBJINTERNAL Core;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /** Pointer to kernel memory cookie. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync ddi_umem_cookie_t Cookie;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** Shadow locked pages. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync void *pvHandle;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** Access during locking. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync int fAccess;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /** Set if large pages are involved in an RTR0MEMOBJTYPE_PHYS
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * allocation. */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync bool fLargePage;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync} RTR0MEMOBJSOL, *PRTR0MEMOBJSOL;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/**
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Returns the physical address for a virtual address.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param pv The virtual address.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @returns The physical address corresponding to @a pv.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsyncstatic uint64_t rtR0MemObjSolVirtToPhys(void *pv)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync{
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync struct hat *pHat = NULL;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync pfn_t PageFrameNum = 0;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync uintptr_t uVirtAddr = (uintptr_t)pv;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (SOL_IS_KRNL_ADDR(pv))
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync pHat = kas.a_hat;
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync else
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync {
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync proc_t *pProcess = (proc_t *)RTR0ProcHandleSelf();
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync AssertRelease(pProcess);
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync pHat = pProcess->p_as->a_hat;
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync }
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync
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));
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync}
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/**
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Returns the physical address for a page.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @param pPage Pointer to the page.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @returns The physical address for a page.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsyncstatic inline uint64_t rtR0MemObjSolPagePhys(page_t *pPage)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync{
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync AssertPtr(pPage);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync pfn_t PageFrameNum = page_pptonum(pPage);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync AssertReleaseMsg(PageFrameNum != PFN_INVALID, ("rtR0MemObjSolPagePhys failed pPage=%p\n"));
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync return (uint64_t)PageFrameNum << PAGESHIFT;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync}
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/**
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Retreives a free page from the kernel freelist.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync *
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 *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @returns Pointer to the allocated page, NULL on failure.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsyncstatic page_t *rtR0MemObjSolPageFromFreelist(caddr_t virtAddr, size_t cbPage)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync{
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync seg_t KernelSeg;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync KernelSeg.s_as = &kas;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync page_t *pPage = page_get_freelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
ad9e5a61fea617d40d07390ff1737277d6aef869vboxsync cbPage, 0 /* flags */, NULL /* NUMA group */);
ad9e5a61fea617d40d07390ff1737277d6aef869vboxsync if ( !pPage
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync && g_frtSolUseKflt)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pPage = page_get_freelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync cbPage, PG_KFLT, NULL /* NUMA group */);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync return pPage;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync}
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/**
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Retrieves a free page from the kernel cachelist.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync *
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 *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @return Pointer to the allocated page, NULL on failure.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsyncstatic page_t *rtR0MemObjSolPageFromCachelist(caddr_t virtAddr, size_t cbPage)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync{
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync seg_t KernelSeg;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync KernelSeg.s_as = &kas;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync page_t *pPage = page_get_cachelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync 0 /* flags */, NULL /* NUMA group */);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if ( !pPage
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync && g_frtSolUseKflt)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync pPage = page_get_cachelist(&s_PageVnode, 0 /* offset */, &KernelSeg, virtAddr,
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync PG_KFLT, NULL /* NUMA group */);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /*
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Remove association with the vnode for pages from the cachelist.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (!PP_ISAGED(pPage))
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync page_hashout(pPage, NULL /* mutex */);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync return pPage;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync}
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/**
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Allocates physical non-contiguous memory.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync *
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 *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * @return Array of allocated pages, NULL on failure.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsyncstatic page_t **rtR0MemObjSolPagesAlloc(uint64_t uPhysHi, uint64_t *puPhys, size_t cb)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync{
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /*
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 *
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync * Reserve available memory for pages and create the pages.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync pgcnt_t cPages = (cb + PAGESIZE - 1) >> PAGESHIFT;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync int rc = page_resv(cPages, KM_NOSLEEP);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (rc)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync rc = page_create_wait(cPages, 0 /* flags */);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (rc)
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync size_t cbPages = cPages * sizeof(page_t *);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync page_t **ppPages = kmem_zalloc(cbPages, KM_SLEEP);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (RT_LIKELY(ppPages))
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync /*
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.
ad9e5a61fea617d40d07390ff1737277d6aef869vboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync caddr_t virtAddr = NULL;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync for (size_t i = 0; i < cPages; i++, virtAddr += PAGESIZE)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync uint32_t cTries = 3;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync page_t *pPage = NULL;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync while (cTries > 0)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync * Get a page from the freelist or cachelist & verify if it's within our
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync * requested range.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pPage = rtR0MemObjSolPageFromFreelist(virtAddr, PAGESIZE);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (!pPage)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pPage = rtR0MemObjSolPageFromCachelist(virtAddr, PAGESIZE);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (RT_UNLIKELY(!pPage))
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync break;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (uPhysHi != NIL_RTHCPHYS)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync uint64_t uPhys = rtR0MemObjSolPagePhys(pPage);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (uPhys > uPhysHi)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync {
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync page_free(pPage, 0 /* don't need page, move to tail of pagelist */);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pPage = NULL;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync --cTries;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync continue;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync }
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync PP_CLRFREE(pPage); /* Page is no longer free */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync PP_CLRAGED(pPage); /* Page is not hashed in */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync ppPages[i] = pPage;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync break;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (RT_UNLIKELY(!pPage))
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /*
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync * No pages found or found pages didn't meet requirements, release what was grabbed so far.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_create_putback(cPages - i);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync while (--i >= 0)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_free(ppPages[i], 0 /* don't need page, move to tail of pagelist */);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync kmem_free(ppPages, cbPages);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync page_unresv(cPages);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return NULL;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /*
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync * We now have the pages locked exclusively, before they are mapped in
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * we must downgrade the lock.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (puPhys)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *puPhys = rtR0MemObjSolPagePhys(ppPages[0]);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return ppPages;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_create_putback(cPages);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_unresv(cPages);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync return NULL;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync}
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync/**
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Prepares pages allocated by rtR0MemObjSolPagesAlloc for mapping.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *
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 * pages.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param cPages The number of pages (entries) in @a auPhys.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @returns IPRT status code.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncstatic int rtR0MemObjSolPagesPreMap(page_t **ppPages, size_t cb, uint64_t auPhys[], size_t cPages)
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync{
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync AssertPtrReturn(ppPages, VERR_INVALID_PARAMETER);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync AssertPtrReturn(auPhys, VERR_INVALID_PARAMETER);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync for (size_t iPage = 0; iPage < cPages; iPage++)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Prepare pages for mapping into kernel/user-space. Downgrade the
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * exclusive page lock to a shared lock to prevent page relocation.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (page_tryupgrade(ppPages[iPage]) == 1)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_downgrade(ppPages[iPage]);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync auPhys[iPage] = rtR0MemObjSolPagePhys(ppPages[iPage]);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync return VINF_SUCCESS;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync}
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync/**
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Frees pages allocated by rtR0MemObjSolPagesAlloc.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param ppPages Pointer to the page list.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param cbPages Size of the allocation.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncstatic void rtR0MemObjSolPagesFree(page_t **ppPages, size_t cb)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync size_t cPages = (cb + PAGESIZE - 1) >> PAGESHIFT;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync size_t cbPages = cPages * sizeof(page_t *);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync for (size_t iPage = 0; iPage < cPages; iPage++)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync /*
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * We need to exclusive lock the pages before freeing them.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync int rc = page_tryupgrade(ppPages[iPage]);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync if (!rc)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync page_unlock(ppPages[iPage]);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync while (!page_lock(ppPages[iPage], SE_EXCL, NULL /* mutex */, P_RECLAIM))
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync /* nothing */;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_free(ppPages[iPage], 0 /* don't need page, move to tail of pagelist */);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync kmem_free(ppPages, cbPages);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_unresv(cPages);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync/**
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Allocates a large page to cover the required allocation size.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *
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 *
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @returns Pointer to the allocated large page, NULL on failure.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncstatic page_t *rtR0MemObjSolLargePageAlloc(uint64_t *puPhys, size_t cb)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Reserve available memory and create the sub-pages.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync const pgcnt_t cPages = cb >> PAGESHIFT;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync int rc = page_resv(cPages, KM_NOSLEEP);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (rc)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync rc = page_create_wait(cPages, 0 /* flags */);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync if (rc)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync /*
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.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync seg_t KernelSeg;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync caddr_t virtAddr = NULL;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync KernelSeg.s_as = &kas;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_t *pRootPage = rtR0MemObjSolPageFromFreelist(virtAddr, cb);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (pRootPage)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync AssertMsg(!(page_pptonum(pRootPage) & (cPages - 1)), ("%p:%lx cPages=%lx\n", pRootPage, page_pptonum(pRootPage), cPages));
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync /*
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 */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync page_t *pPageList = pRootPage;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync for (size_t iPage = 0; iPage < cPages; iPage++)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync page_t *pPage = pPageList;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync AssertPtr(pPage);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync page_sub(&pPageList, pPage);
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync /*
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync * Ensure page is now be free and the page size-code must match that of the root page.
36929067a9d3cba77fd78f1e8fa042ed3a8ae2d6vboxsync */
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync AssertMsg(PP_ISFREE(pPage), ("%p\n", pPage));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync AssertMsg(pPage->p_szc == pRootPage->p_szc, ("%p - %d expected %d \n", pPage, pPage->p_szc, pRootPage->p_szc));
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PP_CLRFREE(pPage); /* Page no longer free */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync PP_CLRAGED(pPage); /* Page no longer hashed-in */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync uint64_t uPhys = rtR0MemObjSolPagePhys(pRootPage);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync AssertMsg(!(uPhys & (cb - 1)), ("%llx %zx\n", uPhys, cb));
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync if (puPhys)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *puPhys = uPhys;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync return pRootPage;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
ab2292e9c32bd271ec91123ef38699a0284b72cbvboxsync
ab2292e9c32bd271ec91123ef38699a0284b72cbvboxsync page_create_putback(cPages);
ab2292e9c32bd271ec91123ef38699a0284b72cbvboxsync }
ab2292e9c32bd271ec91123ef38699a0284b72cbvboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync page_unresv(cPages);
ab2292e9c32bd271ec91123ef38699a0284b72cbvboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
ab2292e9c32bd271ec91123ef38699a0284b72cbvboxsync return NULL;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync}
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync/**
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Prepares the large page allocated by rtR0MemObjSolLargePageAlloc to be mapped.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param pRootPage Pointer to the root page.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param cb Size of the allocation.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @returns IPRT status code.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncstatic int rtR0MemObjSolLargePagePreMap(page_t *pRootPage, size_t cb)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync const pgcnt_t cPages = cb >> PAGESHIFT;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
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));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync /*
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * We need to downgrade the sub-pages from exclusive to shared locking
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * to prevent page relocation.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync for (pgcnt_t iPage = 0; iPage < cPages; iPage++)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync page_t *pPage = page_nextn(pRootPage, iPage);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync AssertMsg(!PP_ISFREE(pPage), ("%p\n", pPage));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (page_tryupgrade(pPage) == 1)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync page_downgrade(pPage);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertMsg(!PP_ISFREE(pPage), ("%p\n", pPage));
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync/**
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Frees the page allocated by rtR0MemObjSolLargePageAlloc.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param pRootPage Pointer to the root page.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param cb Allocated size.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsyncstatic void rtR0MemObjSolLargePageFree(page_t *pRootPage, size_t cb)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pgcnt_t cPages = cb >> PAGESHIFT;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
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));
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /*
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync * We need to exclusively lock the sub-pages before freeing the large one.
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync for (pgcnt_t iPage = 0; iPage < cPages; iPage++)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync page_t *pPage = page_nextn(pRootPage, iPage);
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync AssertMsg(page_pptonum(pPage) == iPage + page_pptonum(pRootPage),
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync ("%p:%lx %lx+%lx\n", pPage, page_pptonum(pPage), iPage, page_pptonum(pRootPage)));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertMsg(!PP_ISFREE(pPage), ("%p\n", pPage));
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync int rc = page_tryupgrade(pPage);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (!rc)
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync page_unlock(pPage);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync while (!page_lock(pPage, SE_EXCL, NULL /* mutex */, P_RECLAIM))
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync /* nothing */;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync /*
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Free the large page and unreserve the memory.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync page_free_pages(pRootPage);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync page_unresv(cPages);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync/**
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync * Unmaps kernel/user-space mapped memory.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * @param pv Pointer to the mapped memory block.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @param cb Size of the memory block.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsyncstatic void rtR0MemObjSolUnmap(void *pv, size_t cb)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync{
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync if (SOL_IS_KRNL_ADDR(pv))
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync hat_unload(kas.a_hat, pv, cb, HAT_UNLOAD | HAT_UNLOAD_UNLOCK);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync vmem_free(heap_arena, pv, cb);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync else
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync struct as *pAddrSpace = ((proc_t *)RTR0ProcHandleSelf())->p_as;
49e54e2ffe0c10864d06e9d1ebe24a8eb1327a6bvboxsync AssertPtr(pAddrSpace);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync as_rangelock(pAddrSpace);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync as_unmap(pAddrSpace, pv, cb);
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync as_rangeunlock(pAddrSpace);
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync/**
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Lock down memory mappings for a virtual address.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *
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 *
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @returns IPRT status code.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncstatic int rtR0MemObjSolLock(void *pv, size_t cb, int fPageAccess)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Kernel memory mappings on x86/amd64 are always locked, only handle user-space memory.
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync */
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync if (!SOL_IS_KRNL_ADDR(pv))
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync proc_t *pProc = (proc_t *)RTR0ProcHandleSelf();
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync AssertPtr(pProc);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync faultcode_t rc = as_fault(pProc->p_as->a_hat, pProc->p_as, (caddr_t)pv, cb, F_SOFTLOCK, fPageAccess);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync if (rc)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync LogRel(("rtR0MemObjSolLock failed for pv=%pv cb=%lx fPageAccess=%d rc=%d\n", pv, cb, fPageAccess, rc));
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync return VERR_LOCK_FAILED;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync }
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync return VINF_SUCCESS;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync}
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync/**
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync * Unlock memory mappings for a virtual address.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync *
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).
91f8453d16b48876deddaba298c211071d0ca3a5vboxsync */
91f8453d16b48876deddaba298c211071d0ca3a5vboxsyncstatic void rtR0MemObjSolUnlock(void *pv, size_t cb, int fPageAccess)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (!SOL_IS_KRNL_ADDR(pv))
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync proc_t *pProcess = (proc_t *)RTR0ProcHandleSelf();
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertPtr(pProcess);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync as_fault(pProcess->p_as->a_hat, pProcess->p_as, (caddr_t)pv, cb, F_SOFTUNLOCK, fPageAccess);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync}
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync/**
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * Maps a list of physical pages into user address space.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync *
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 *
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync * @returns IPRT status code.
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync */
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsyncstatic int rtR0MemObjSolUserMap(caddr_t *pVirtAddr, unsigned fPageAccess, uint64_t *paPhysAddrs, size_t cb)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync{
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync struct as *pAddrSpace = ((proc_t *)RTR0ProcHandleSelf())->p_as;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync int rc = VERR_INTERNAL_ERROR;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync SEGVBOX_CRARGS Args;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync Args.paPhysAddrs = paPhysAddrs;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync Args.fPageAccess = fPageAccess;
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync as_rangelock(pAddrSpace);
6efcf94383d6e48c764c6518cf1b4069ad34e210vboxsync map_addr(pVirtAddr, cb, 0 /* offset */, 0 /* vacalign */, MAP_SHARED);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (*pVirtAddr != NULL)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = as_map(pAddrSpace, *pVirtAddr, cb, rtR0SegVBoxSolCreate, &Args);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync rc = ENOMEM;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync as_rangeunlock(pAddrSpace);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return RTErrConvertFromErrno(rc);
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync}
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsyncDECLHIDDEN(int) rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync{
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)pMem;
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync switch (pMemSolaris->Core.enmType)
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync {
d29ab0cfbeef254251f0a2458163034999abb8a0vboxsync case RTR0MEMOBJTYPE_LOW:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0SolMemFree(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync break;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync case RTR0MEMOBJTYPE_PHYS:
9e4ea89b1085fdaa5861e45a729d9c978db1a8f1vboxsync if (pMemSolaris->Core.u.Phys.fAllocated)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (pMemSolaris->fLargePage)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjSolLargePageFree(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync rtR0SolMemFree(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync break;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync case RTR0MEMOBJTYPE_PHYS_NC:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjSolPagesFree(pMemSolaris->pvHandle, pMemSolaris->Core.cb);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync break;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync case RTR0MEMOBJTYPE_PAGE:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync ddi_umem_free(pMemSolaris->Cookie);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync break;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync case RTR0MEMOBJTYPE_LOCK:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjSolUnlock(pMemSolaris->Core.pv, pMemSolaris->Core.cb, pMemSolaris->fAccess);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync break;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync case RTR0MEMOBJTYPE_MAPPING:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjSolUnmap(pMemSolaris->Core.pv, pMemSolaris->Core.cb);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync break;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync case RTR0MEMOBJTYPE_RES_VIRT:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (pMemSolaris->Core.u.ResVirt.R0Process == NIL_RTR0PROCESS)
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync vmem_xfree(heap_arena, pMemSolaris->Core.pv, pMemSolaris->Core.cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync else
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertFailed();
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync break;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync case RTR0MEMOBJTYPE_CONT: /* we don't use this type here. */
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync default:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertMsgFailed(("enmType=%d\n", pMemSolaris->Core.enmType));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_INTERNAL_ERROR;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Create the object. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PAGE, NULL, cb);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (RT_UNLIKELY(!pMemSolaris))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync void *pvMem = ddi_umem_alloc(cb, DDI_UMEM_SLEEP, &pMemSolaris->Cookie);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (RT_UNLIKELY(!pvMem))
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjDelete(&pMemSolaris->Core);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NO_PAGE_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.pv = pvMem;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->pvHandle = NULL;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync *ppMem = &pMemSolaris->Core;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync{
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync NOREF(fExecutable);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync /* Create the object */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOW, NULL, cb);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (!pMemSolaris)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Allocate physically low page-aligned memory. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync uint64_t uPhysHi = _4G - 1;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync void *pvMem = rtR0SolMemAlloc(uPhysHi, NULL /* puPhys */, cb, PAGESIZE, false /* fContig */);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (RT_UNLIKELY(!pvMem))
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjDelete(&pMemSolaris->Core);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NO_LOW_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.pv = pvMem;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->pvHandle = NULL;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync *ppMem = &pMemSolaris->Core;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsyncDECLHIDDEN(int) rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync NOREF(fExecutable);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return rtR0MemObjNativeAllocPhys(ppMem, cb, _4G - 1, PAGE_SIZE /* alignment */);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#if HC_ARCH_BITS == 64
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS_NC, NULL, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (RT_UNLIKELY(!pMemSolaris))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NO_MEMORY;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync uint64_t PhysAddr = UINT64_MAX;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync void *pvPages = rtR0MemObjSolPagesAlloc((uint64_t)PhysHighest, &PhysAddr, cb);
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync if (!pvPages)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync LogRel(("rtR0MemObjNativeAllocPhysNC: rtR0MemObjSolPagesAlloc failed for cb=%u.\n", cb));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjDelete(&pMemSolaris->Core);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.pv = NULL;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->pvHandle = pvPages;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync Assert(PhysAddr != UINT64_MAX);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync Assert(!(PhysAddr & PAGE_OFFSET_MASK));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync *ppMem = &pMemSolaris->Core;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#else /* 32 bit: */
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync return VERR_NOT_SUPPORTED; /* see the RTR0MemObjAllocPhysNC specs */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#endif
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsyncDECLHIDDEN(int) rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertMsgReturn(PhysHighest >= 16 *_1M, ("PhysHigest=%RHp\n", PhysHighest), VERR_NOT_SUPPORTED);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS, NULL, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (RT_UNLIKELY(!pMemSolaris))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Allocating one large page gets special treatment.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync static uint32_t s_cbLargePage = UINT32_MAX;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (s_cbLargePage == UINT32_MAX)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync#if 0 /* currently not entirely stable, so disabled. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (page_num_pagesizes() > 1)
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync ASMAtomicWriteU32(&s_cbLargePage, page_get_pagesize(1));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync else
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync#endif
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync ASMAtomicWriteU32(&s_cbLargePage, 0);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync uint64_t PhysAddr;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if ( cb == s_cbLargePage
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync && cb == uAlignment
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync && PhysHighest == NIL_RTHCPHYS)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Allocate one large page.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync void *pvPages = rtR0MemObjSolLargePageAlloc(&PhysAddr, cb);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (RT_LIKELY(pvPages))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertMsg(!(PhysAddr & (cb - 1)), ("%RHp\n", PhysAddr));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.pv = NULL;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.u.Phys.PhysBase = PhysAddr;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.u.Phys.fAllocated = true;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync pMemSolaris->pvHandle = pvPages;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->fLargePage = true;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync *ppMem = &pMemSolaris->Core;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync else
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Allocate physically contiguous memory aligned as specified.
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertCompile(NIL_RTHCPHYS == UINT64_MAX);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PhysAddr = PhysHighest;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync void *pvMem = rtR0SolMemAlloc(PhysHighest, &PhysAddr, cb, uAlignment, true /* fContig */);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (RT_LIKELY(pvMem))
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync Assert(!(PhysAddr & PAGE_OFFSET_MASK));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync Assert(PhysAddr < PhysHighest);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync Assert(PhysAddr + cb <= PhysHighest);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.pv = pvMem;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync pMemSolaris->Core.u.Phys.PhysBase = PhysAddr;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.u.Phys.fAllocated = true;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pMemSolaris->pvHandle = NULL;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pMemSolaris->fLargePage = false;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync *ppMem = &pMemSolaris->Core;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjDelete(&pMemSolaris->Core);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync return VERR_NO_CONT_MEMORY;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncDECLHIDDEN(int) rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync AssertReturn(uCachePolicy == RTMEM_CACHE_POLICY_DONT_CARE, VERR_NOT_SUPPORTED);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync /* Create the object. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_PHYS, NULL, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (!pMemSolaris)
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync return VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync /* There is no allocation here, it needs to be mapped somewhere first. */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pMemSolaris->Core.u.Phys.fAllocated = false;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync pMemSolaris->Core.u.Phys.PhysBase = Phys;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pMemSolaris->Core.u.Phys.uCachePolicy = uCachePolicy;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *ppMem = &pMemSolaris->Core;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess,
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync RTR0PROCESS R0Process)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertReturn(R0Process == RTR0ProcHandleSelf(), VERR_INVALID_PARAMETER);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync NOREF(fAccess);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Create the locking object */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (!pMemSolaris)
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync return VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Lock down user pages. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync int fPageAccess = S_READ;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (fAccess & RTMEM_PROT_WRITE)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync fPageAccess = S_WRITE;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (fAccess & RTMEM_PROT_EXEC)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync fPageAccess = S_EXEC;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync int rc = rtR0MemObjSolLock((void *)R3Ptr, cb, fPageAccess);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (RT_FAILURE(rc))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync LogRel(("rtR0MemObjNativeLockUser: rtR0MemObjSolLock failed rc=%d\n", rc));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjDelete(&pMemSolaris->Core);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return rc;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /* Fill in the object attributes and return successfully. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.u.Lock.R0Process = R0Process;
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync pMemSolaris->pvHandle = NULL;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->fAccess = fPageAccess;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync *ppMem = &pMemSolaris->Core;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncDECLHIDDEN(int) rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync{
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync NOREF(fAccess);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_LOCK, pv, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (!pMemSolaris)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync /* Lock down kernel pages. */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync int fPageAccess = S_READ;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (fAccess & RTMEM_PROT_WRITE)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync fPageAccess = S_WRITE;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (fAccess & RTMEM_PROT_EXEC)
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync fPageAccess = S_EXEC;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync int rc = rtR0MemObjSolLock(pv, cb, fPageAccess);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (RT_FAILURE(rc))
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync LogRel(("rtR0MemObjNativeLockKernel: rtR0MemObjSolLock failed rc=%d\n", rc));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rtR0MemObjDelete(&pMemSolaris->Core);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync return rc;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /* Fill in the object attributes and return successfully. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.u.Lock.R0Process = NIL_RTR0PROCESS;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync pMemSolaris->pvHandle = NULL;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->fAccess = fPageAccess;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync *ppMem = &pMemSolaris->Core;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync PRTR0MEMOBJSOL pMemSolaris;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Use xalloc.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync void *pv = vmem_xalloc(heap_arena, cb, uAlignment, 0 /* phase */, 0 /* nocross */,
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync NULL /* minaddr */, NULL /* maxaddr */, VM_SLEEP);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (RT_UNLIKELY(!pv))
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync /* Create the object. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_RES_VIRT, pv, cb);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (!pMemSolaris)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync LogRel(("rtR0MemObjNativeReserveKernel failed to alloc memory object.\n"));
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync vmem_xfree(heap_arena, pv, cb);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pMemSolaris->Core.u.ResVirt.R0Process = NIL_RTR0PROCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync *ppMem = &pMemSolaris->Core;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsyncDECLHIDDEN(int) rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync return VERR_NOT_SUPPORTED;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsyncDECLHIDDEN(int) rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync unsigned fProt, size_t offSub, size_t cbSub)
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync{
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /** @todo rtR0MemObjNativeMapKernel / Solaris - Should be fairly simple alloc kernel memory and memload it. */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NOT_SUPPORTED;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsyncDECLHIDDEN(int) rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, PRTR0MEMOBJINTERNAL pMemToMap, RTR3PTR R3PtrFixed,
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync{
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Fend off things we cannot do.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync AssertMsgReturn(R3PtrFixed == (RTR3PTR)-1, ("%p\n", R3PtrFixed), VERR_NOT_SUPPORTED);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (uAlignment != PAGE_SIZE)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NOT_SUPPORTED;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
e214bb78026c1d64078b34ca9504d3f5abbc52efvboxsync * Get parameters from the source object.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync PRTR0MEMOBJSOL pMemToMapSolaris = (PRTR0MEMOBJSOL)pMemToMap;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync void *pv = pMemToMapSolaris->Core.pv;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync size_t cb = pMemToMapSolaris->Core.cb;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync size_t cPages = cb >> PAGE_SHIFT;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Create the mapping object
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync */
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync PRTR0MEMOBJSOL pMemSolaris;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync pMemSolaris = (PRTR0MEMOBJSOL)rtR0MemObjNew(sizeof(*pMemSolaris), RTR0MEMOBJTYPE_MAPPING, pv, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (RT_UNLIKELY(!pMemSolaris))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync int rc = VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync uint64_t *paPhysAddrs = kmem_zalloc(sizeof(uint64_t) * cPages, KM_SLEEP);
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync if (RT_LIKELY(paPhysAddrs))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Prepare the pages according to type.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
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 && pMemToMapSolaris->fLargePage)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync RTHCPHYS Phys = pMemToMapSolaris->Core.u.Phys.PhysBase;
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync for (pgcnt_t iPage = 0; iPage < cPages; iPage++, Phys += PAGE_SIZE)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync paPhysAddrs[iPage] = Phys;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync rc = rtR0MemObjSolLargePagePreMap(pMemToMapSolaris->pvHandle, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync else
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync /*
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync * Have kernel mapping, just translate virtual to physical.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync AssertPtr(pv);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = VINF_SUCCESS;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync for (size_t iPage = 0; iPage < cPages; iPage++)
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync paPhysAddrs[iPage] = rtR0MemObjSolVirtToPhys(pv);
fc148a6b23d25a87561beaffe0ba06c3ba93bf5avboxsync if (RT_UNLIKELY(paPhysAddrs[iPage] == -(uint64_t)1))
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync LogRel(("rtR0MemObjNativeMapUser: no page to map.\n"));
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync rc = VERR_MAP_FAILED;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync break;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync pv = (void *)((uintptr_t)pv + PAGE_SIZE);
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync if (RT_SUCCESS(rc))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync unsigned fPageAccess = PROT_READ;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (fProt & RTMEM_PROT_WRITE)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync fPageAccess |= PROT_WRITE;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync if (fProt & RTMEM_PROT_EXEC)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync fPageAccess |= PROT_EXEC;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync * Perform the actual mapping.
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync caddr_t UserAddr = NULL;
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync rc = rtR0MemObjSolUserMap(&UserAddr, fPageAccess, paPhysAddrs, cb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (RT_SUCCESS(rc))
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync pMemSolaris->Core.u.Mapping.R0Process = R0Process;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync pMemSolaris->Core.pv = UserAddr;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync *ppMem = &pMemSolaris->Core;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return VINF_SUCCESS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync LogRel(("rtR0MemObjNativeMapUser: rtR0MemObjSolUserMap failed rc=%d.\n", rc));
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync rc = VERR_MAP_FAILED;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync kmem_free(paPhysAddrs, sizeof(uint64_t) * cPages);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
57b49c1557a310ee615bc0ee79dd2a2e92319a1bvboxsync else
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync rc = VERR_NO_MEMORY;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync rtR0MemObjDelete(&pMemSolaris->Core);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync return rc;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync}
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsyncDECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync{
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync NOREF(pMem);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync NOREF(offSub);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync NOREF(cbSub);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync NOREF(fProt);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return VERR_NOT_SUPPORTED;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
32750ad95d5e2fe4bb368e751875b33094cfa973vboxsync
32750ad95d5e2fe4bb368e751875b33094cfa973vboxsync
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsyncDECLHIDDEN(RTHCPHYS) rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync{
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync PRTR0MEMOBJSOL pMemSolaris = (PRTR0MEMOBJSOL)pMem;
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync
2a5e5a032e6f23f8937718e4ee4d6979188bdd19vboxsync switch (pMemSolaris->Core.enmType)
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync {
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync case RTR0MEMOBJTYPE_PHYS_NC:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync if (pMemSolaris->Core.u.Phys.fAllocated)
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return rtR0MemObjSolVirtToPhys(pb);
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync }
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync page_t **ppPages = pMemSolaris->pvHandle;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return rtR0MemObjSolPagePhys(ppPages[iPage]);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync case RTR0MEMOBJTYPE_PAGE:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync case RTR0MEMOBJTYPE_LOW:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync case RTR0MEMOBJTYPE_LOCK:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync {
71c8a528203c289a8585ce10ac6bafc4274058c6vboxsync uint8_t *pb = (uint8_t *)pMemSolaris->Core.pv + ((size_t)iPage << PAGE_SHIFT);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return rtR0MemObjSolVirtToPhys(pb);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync /*
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.
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync case RTR0MEMOBJTYPE_MAPPING:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync return rtR0MemObjNativeGetPagePhysAddr(pMemSolaris->Core.uRel.Child.pParent, iPage);
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync case RTR0MEMOBJTYPE_CONT:
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync case RTR0MEMOBJTYPE_PHYS:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync AssertFailed(); /* handled by the caller */
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync case RTR0MEMOBJTYPE_RES_VIRT:
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync default:
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync return NIL_RTHCPHYS;
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync }
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync}
2823fbb1428e982169f04923472d7c94e7ed8385vboxsync
147e101bcd061b5e085e4a2c0cc9fc35546ff1aavboxsync