memobj-r0drv-nt.cpp revision e5f6ad85110ebdc7256808a0a3a8ce330370be6a
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/* $Id$ */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/** @file
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * innotek Portable Runtime - Ring-0 Memory Objects, NT.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Copyright (C) 2006-2007 innotek GmbH
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync *
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * available from http://www.virtualbox.org. This file is free software;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * you can redistribute it and/or modify it under the terms of the GNU
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * General Public License as published by the Free Software Foundation,
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/*******************************************************************************
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync* Header Files *
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync*******************************************************************************/
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#include "the-nt-kernel.h"
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#include <iprt/memobj.h>
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#include <iprt/alloc.h>
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#include <iprt/assert.h>
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#include <iprt/log.h>
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#include <iprt/param.h>
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#include <iprt/string.h>
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#include <iprt/process.h>
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#include "internal/memobj.h"
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/*******************************************************************************
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync* Defined Constants And Macros *
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync*******************************************************************************/
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/** Maximum number of bytes we try to lock down in one go.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * This is supposed to have a limit right below 256MB, but this appears
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * to actually be much lower. The values here have been determined experimentally.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#ifdef RT_ARCH_X86
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync# define MAX_LOCK_MEM_SIZE (32*1024*1024) /* 32MB */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#endif
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#ifdef RT_ARCH_AMD64
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync# define MAX_LOCK_MEM_SIZE (24*1024*1024) /* 24MB */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#endif
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/*******************************************************************************
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync* Structures and Typedefs *
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync*******************************************************************************/
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/**
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * The NT version of the memory object structure.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsynctypedef struct RTR0MEMOBJNT
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /** The core structure. */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync RTR0MEMOBJINTERNAL Core;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#ifndef IPRT_TARGET_NT4
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /** Used MmAllocatePagesForMdl(). */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync bool fAllocatedPagesForMdl;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#endif
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /** The number of PMDLs (memory descriptor lists) in the array. */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync unsigned cMdls;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /** Array of MDL pointers. (variable size) */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PMDL apMdls[1];
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync} RTR0MEMOBJNT, *PRTR0MEMOBJNT;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncint rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)pMem;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Deal with it on a per type basis (just as a variation).
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync switch (pMemNt->Core.enmType)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync case RTR0MEMOBJTYPE_LOW:
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#ifdef IPRT_TARGET_NT4
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMemNt->fAllocatedPagesForMdl)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Assert(pMemNt->Core.pv && pMemNt->cMdls == 1 && pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmUnmapLockedPages(pMemNt->Core.pv, pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.pv = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmFreePagesFromMdl(pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 0;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync break;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#endif
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /* fall thru */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync case RTR0MEMOBJTYPE_PAGE:
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Assert(pMemNt->Core.pv);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync ExFreePool(pMemNt->Core.pv);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.pv = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Assert(pMemNt->cMdls == 1 && pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync IoFreeMdl(pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 0;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync break;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync case RTR0MEMOBJTYPE_CONT:
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Assert(pMemNt->Core.pv);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmFreeContiguousMemory(pMemNt->Core.pv);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.pv = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Assert(pMemNt->cMdls == 1 && pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync IoFreeMdl(pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 0;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync break;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync case RTR0MEMOBJTYPE_PHYS:
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync case RTR0MEMOBJTYPE_PHYS_NC:
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#ifdef IPRT_TARGET_NT4
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMemNt->fAllocatedPagesForMdl)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmFreePagesFromMdl(pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 0;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#endif
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync break;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync case RTR0MEMOBJTYPE_LOCK:
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync for (unsigned i = 0; i < pMemNt->cMdls; i++)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync MmUnlockPages(pMemNt->apMdl[i]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync IoFreeMdl(pMemNt->apMdl[i]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdl[i] = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync break;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync case RTR0MEMOBJTYPE_RES_VIRT:
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMemNt->Core.u.ResVirt.R0Process == NIL_RTR0PROCESS)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmMapIoSpace
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync else
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync AssertMsgFailed(("RTR0MEMOBJTYPE_RES_VIRT\n"));
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VERR_INTERNAL_ERROR;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync break;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync case RTR0MEMOBJTYPE_MAPPING:
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Assert(pMemNt->Core.pv && pMemNt->cMdls == 1 && pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PRTR0MEMOBJNT pMemNtParent = (PRTR0MEMOBJNT)pMemNt->Core.uRel.Child.pParent;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Assert(pMemNtParent);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Assert(pMemNtParent->cMdls == 1 && pMemNtParent->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmUnmapLockedPages(pMemNt->Core.pv, pMemNtParent->apMdls);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.pv = NULL;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync break;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync default:
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync AssertMsgFailed(("enmType=%d\n", pMemNt->Core.enmType));
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VERR_INTERNAL_ERROR;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VINF_SUCCESS;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncint rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Try allocate the memory and create an MDL for them so
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * we can query the physical addresses and do mappings later
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * without running into out-of-memory conditions and similar problems.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync int rc = VERR_NO_PAGE_MEMORY;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync void *pv = ExAllocatePoolWithTag(NonPagedPool, cb, IPRT_NT_POOL_TAG);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pv)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PMDL pMdl = IoAllocateMdl(pv, cb, FALSE, FALSE, NULL);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMdl)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmBuildMdlForNonPagedPool(pMdl);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /** @todo if (fExecutable) */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Create the IPRT memory object.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_PAGE, pv, cb);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pMemNt)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 1;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = pMdl;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync *ppMem = &pMemNt->Core;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VINF_SUCCESS;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync rc = VERR_NO_MEMORY;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync IoFreeMdl(pMdl);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync ExFreePool(pv);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return rc;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncint rtR0MemObjNativeAllocLow(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Try see if we get lucky first...
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * (We could probably just assume we're lucky on NT4.)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync int rc = rtR0MemObjNativeAllocPage(ppMem, cb, fExecutable);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (RT_SUCCESS(rc))
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync size_t iPage = cb >> PAGE_SHIFT;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync while (iPage-- > 0)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (rtR0MemObjNativeGetPagePhysAddr(*ppMem, iPage) >= _4G)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync rc = VERR_NO_MEMORY;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync break;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (RT_SUCCESS(rc))
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return rc;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /* The following ASSUMES that rtR0MemObjNativeAllocPage returns a completed object. */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync RTR0MemObjFree(*ppMem, false);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync *ppMem = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#ifndef IPRT_TARGET_NT4
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Use MmAllocatePagesForMdl to specify the range of physical addresses we wish to use.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PHYSICAL_ADDRESS Zero;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PHYSICAL_ADDRESS HighAddr;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Zero.QuadPart = 0;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync High.QuadPart = _4G - 1;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PMDL pMdl = MmAllocatePagesForMdl(Zero, HighAddr, Zero, cb);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMdl)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (MmGetMdlByteCount(pMdl) >= cb)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync __try
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync void *pv = MmMapLockedPagesSpecifyCache(pMdl, KernelMode, MmCached, NULL /* no base address */,
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync FALSE /* no bug check on failure */, NormalPagePriority);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pv)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_LOW, pv, cb);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMemNt)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->fAllocatedPagesForMdl = true;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 1;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = pMdl;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync *ppMem = &pMemNt->Core;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VINF_SUCCESS;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmUnmapLockedPages(pv, pMdl);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync __except(EXCEPTION_EXECUTE_HANDLER)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /* nothing */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmFreePagesFromMdl(pMdl);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#endif /* !IPRT_TARGET_NT4 */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Fall back on contiguous memory...
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return rtR0MemObjNativeAllocCont(ppMem, cb, fExecutable);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync/**
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Internal worker for rtR0MemObjNativeAllocCont(), rtR0MemObjNativeAllocPhys()
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * and rtR0MemObjNativeAllocPhysNC() that takes a max physical address in addition
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * to what rtR0MemObjNativeAllocCont() does.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync *
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * @returns IPRT status code.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * @param ppMem Where to store the pointer to the ring-0 memory object.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * @param cb The size.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * @param fExecutable Whether the mapping should be executable or not.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * @param PhysHighest The highest physical address for the pages in allocation.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsyncstatic int rtR0MemObjNativeAllocContEx(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable, RTHCPHYS PhysHighest)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Allocate the memory and create an MDL for it.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PHYSICAL_ADDRESS PhysAddrHighest;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PhysAddrHighest.QuadPart = PhysHighest;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync void *pv = MmAllocateContiguousMemory(cb, PhysAddrHighest);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (!pv)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VERR_NO_MEMORY;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PMDL pMdl = IoAllocateMdl(pv, cb, FALSE, FALSE, NULL);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMdl)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmBuildMdlForNonPagedPool(pMdl);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /** @todo fExecutable */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_CONT, pv, cb);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMemNt)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.u.Cont.Phys = (RTHCPHYS)*MmGetMdlPfnArray(pMdl) << PAGE_SHIFT;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 1;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = pMdl;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync *ppMem = &pMemNt->Core;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VINF_SUCCESS;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync IoFreeMdl(pMdl);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmFreeContiguousMemory(pv);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VERR_NO_MEMORY;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync}
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsyncint rtR0MemObjNativeAllocCont(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync{
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return rtR0MemObjNativeAllocContEx(ppMem, cb, fExecutable, _4G-1);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncint rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#ifndef IPRT_TARGET_NT4
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Try and see if we're lucky and get a contiguous chunk from MmAllocatePagesForMdl.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync *
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * If the allocation is big, the chances are *probably* not very good. The current
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * max limit is kind of random.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (cb < _128K)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PHYSICAL_ADDRESS Zero;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PHYSICAL_ADDRESS HighAddr;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Zero.QuadPart = 0;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync High.QuadPart = _4G - 1;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PMDL pMdl = MmAllocatePagesForMdl(Zero, HighAddr, Zero, cb);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMdl)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (MmGetMdlByteCount(pMdl) >= cb)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PPFN_NUMBER paPfns = MmGetMdlPfnArray(pMdl);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PFN_NUMBER Pfn = paPfns[0] + 1;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync const size_t cPages = cb >> PAGE_SIZE;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync size_t iPage;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync for (iPage = 1; iPage < cPages; iPage++, Pfn++)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (paPfns[iPage] != Pfn)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync break;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (iPage >= cPages)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_PHYS, NULL, cb);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMemNt)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.u.Phys.fAllocated = true;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.u.Phys.PhysBase = (RTHCPHYS)paPfns[0] << PAGE_SHIFT;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->fAllocatedPagesForMdl = true;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 1;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = pMdl;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync *ppMem = &pMemNt->Core;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VINF_SUCCESS;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmFreePagesFromMdl(pMdl);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#endif
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return rtR0MemObjNativeAllocContEx(ppMem, cb, false, PhysHighest);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
c5d2523548cc57504b829f53f1362b848a84542cvboxsyncint rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
c5d2523548cc57504b829f53f1362b848a84542cvboxsync{
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#ifndef IPRT_TARGET_NT4
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PHYSICAL_ADDRESS Zero;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PHYSICAL_ADDRESS HighAddr;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Zero.QuadPart = 0;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync High.QuadPart = _4G - 1;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PMDL pMdl = MmAllocatePagesForMdl(Zero, HighAddr, Zero, cb);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMdl)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (MmGetMdlByteCount(pMdl) >= cb)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_CONT, pv, cb);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMemNt)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->fAllocatedPagesForMdl = true;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 1;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = pMdl;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync *ppMem = &pMemNt->Core;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VINF_SUCCESS;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmFreePagesFromMdl(pMdl);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VERR_NO_MEMORY;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#else /* IPRT_TARGET_NT4 */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VERR_NOT_SUPPORTED;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#endif /* IPRT_TARGET_NT4 */
c5d2523548cc57504b829f53f1362b848a84542cvboxsync}
c5d2523548cc57504b829f53f1362b848a84542cvboxsync
c5d2523548cc57504b829f53f1362b848a84542cvboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncint rtR0MemObjNativeEnterPhys(PPRTR0MEMOBJINTERNAL ppMem, RTHCPHYS Phys, size_t cb)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Validate the address range and create a descriptor for it.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PFN_NUMBER Pfn = Phys >> PAGE_SHIFT;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (((RTHCPHYS)Pfn << PAGE_SHIFT) != Phys)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VERR_ADDRESS_TOO_BIG;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Create the IPRT memory object.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_PHYS, NULL, cb);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMemNt)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.u.Phys.PhysBase = PhysAddr;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.u.Phys.fAllocated = false;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->pMemDesc = pMemDesc;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync *ppMem = &pMemNt->Core;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VINF_SUCCESS;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VERR_NO_MEMORY;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/**
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Internal worker for locking down pages.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync *
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * @return IPRT status code.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync *
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * @param ppMem Where to store the memory object pointer.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * @param pv First page.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * @param cb Number of bytes.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * @param Task The task \a pv and \a cb refers to.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsyncstatic int rtR0MemObjNtLock(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, RTR0PROCESS R0Process)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Calc the number of MDLs we need and allocate the memory object structure.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync unsigned cMdls = pMem->cb / MAX_LOCK_MEM_SIZE;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if ((pMem->cb % MAX_LOCK_MEM_SIZE) > 0)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync cMdls++;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJNT, apMdls[cMdls]),
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync RTR0MEMOBJTYPE_LOCK, (void *)R3Ptr, cb);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (!pMemNt)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VERR_NO_MEMORY;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Loop locking down the sub parts of the memory.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync int rc = VINF_SUCCESS;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync size_t cbTotal = 0;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync uint8_t *pb = pv;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync unsigned iMdl;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync for (iMdl = 0; iMdl < cMdls; iMdl++)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Calc the Mdl size and allocate it.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync size_t cbCur = cb - cbTotal;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (cbCur > MAX_LOCK_MEM_SIZE)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync cbCur = MAX_LOCK_MEM_SIZE;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync AssertMsg(cbCur, ("cbCur: 0!\n"));
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PMDL pMdl = IoAllocateMdl(pb, cbCur, FALSE, FALSE, NULL);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (!pMdl)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync rc = VERR_NO_MEMORY;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync break;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Lock the pages.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync __try
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmProbeAndLockPages(pMdl, R0Process == NIL_RTR0PROCESS ? KernelMode : UserMode, IoModifyAccess);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[iMdl] = pMdl;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls++;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync __except(EXCEPTION_EXECUTE_HANDLER)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync IoFreeMdl(pMdl);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync rc = VERR_LOCK_FAILED;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync break;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /* next */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync cbTotal += cbCur;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pb += cbCur;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (RT_SUCCESS(rc))
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Assert(pMemNt->cMdls == cMdls);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.u.Lock.R0Process = R0Process;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync *ppMem = &pMemNt->Core;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return rc;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * We failed, perform cleanups.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync while (iMdl-- > 0)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmUnlockPages(pMemNt->apMdl[iMdl]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync IoFreeMdl(pMemNt->apMdl[iMdl]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdl[iMdl] = NULL;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync rtR0MemObjDelete(pMemNt);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return SUPDRV_ERR_LOCK_FAILED;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsyncint rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, RTR0PROCESS R0Process)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /* ( Can use MmProbeAndLockProcessPages if we need to mess with other processes later.) */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return rtR0MemObjNtLock(ppMem, (void *)R3Ptr, cb, R0Process);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncint rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return rtR0MemObjNtLock(ppMem, (void *)R3Ptr, cb, NIL_RTR0PROCESS);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncint rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VERR_NOT_IMPLEMENTED;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
c5d2523548cc57504b829f53f1362b848a84542cvboxsyncint rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VERR_NOT_IMPLEMENTED;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncint rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment, unsigned fProt)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Must have a memory descriptor.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync int rc = VERR_INVALID_PARAMETER;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PRTR0MEMOBJNT pMemToMapDarwin = (PRTR0MEMOBJNT)pMemToMap;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pMemToMapDarwin->pMemDesc)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync IOMemoryMap *pMemMap = pMemToMapDarwin->pMemDesc->map(kernel_task, kIOMapAnywhere,
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync kIOMapAnywhere | kIOMapDefaultCache);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pMemMap)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync IOVirtualAddress VirtAddr = pMemMap->getVirtualAddress();
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync void *pv = (void *)(uintptr_t)VirtAddr;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if ((uintptr_t)pv == VirtAddr)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Create the IPRT memory object.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_MAPPING,
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pv, pMemToMapDarwin->Core.cb);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pMemNt)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pMemNt->Core.u.Mapping.R0Process = NIL_RTR0PROCESS;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pMemNt->pMemMap = pMemMap;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync *ppMem = &pMemNt->Core;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VINF_SUCCESS;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync rc = VERR_NO_MEMORY;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync else
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync rc = VERR_ADDRESS_TOO_BIG;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pMemMap->release();
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync else
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync rc = VERR_MAP_FAILED;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return rc;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
c5d2523548cc57504b829f53f1362b848a84542cvboxsyncint rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Must have a memory descriptor.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync int rc = VERR_INVALID_PARAMETER;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PRTR0MEMOBJNT pMemToMapDarwin = (PRTR0MEMOBJNT)pMemToMap;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pMemToMapDarwin->pMemDesc)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync IOMemoryMap *pMemMap = pMemToMapDarwin->pMemDesc->map((task_t)R0Process, kIOMapAnywhere,
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync kIOMapAnywhere | kIOMapDefaultCache);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pMemMap)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync IOVirtualAddress VirtAddr = pMemMap->getVirtualAddress();
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync void *pv = (void *)(uintptr_t)VirtAddr;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if ((uintptr_t)pv == VirtAddr)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Create the IPRT memory object.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_MAPPING,
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pv, pMemToMapDarwin->Core.cb);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pMemNt)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pMemNt->Core.u.Mapping.R0Process = R0Process;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pMemNt->pMemMap = pMemMap;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync *ppMem = &pMemNt->Core;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VINF_SUCCESS;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync rc = VERR_NO_MEMORY;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync else
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync rc = VERR_ADDRESS_TOO_BIG;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pMemMap->release();
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync else
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync rc = VERR_MAP_FAILED;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return rc;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncRTHCPHYS rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, unsigned iPage)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync RTHCPHYS PhysAddr;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)pMem;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#ifdef USE_VM_MAP_WIRE
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Locked memory doesn't have a memory descriptor and
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * needs to be handled differently.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pMemNt->Core.enmType == RTR0MEMOBJTYPE_LOCK)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync ppnum_t PgNo;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pMemNt->Core.u.Lock.R0Process == NIL_RTR0PROCESS)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PgNo = pmap_find_phys(kernel_pmap, (uintptr_t)pMemNt->Core.pv + iPage * PAGE_SIZE);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync else
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * From what I can tell, Apple seems to have locked up the all the
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * available interfaces that could help us obtain the pmap_t of a task
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * or vm_map_t.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * So, we'll have to figure out where in the vm_map_t structure it is
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * and read it our selves. ASSUMING that kernel_pmap is pointed to by
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * kernel_map->pmap, we scan kernel_map to locate the structure offset.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Not nice, but it will hopefully do the job in a reliable manner...
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync *
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * (get_task_pmap, get_map_pmap or vm_map_pmap is what we really need btw.)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync static int s_offPmap = -1;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (RT_UNLIKELY(s_offPmap == -1))
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pmap_t const *p = (pmap_t *)kernel_map;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pmap_t const * const pEnd = p + 64;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync for (; p < pEnd; p++)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (*p == kernel_pmap)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync s_offPmap = (uintptr_t)p - (uintptr_t)kernel_map;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync break;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync AssertReturn(s_offPmap >= 0, NIL_RTHCPHYS);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pmap_t Pmap = *(pmap_t *)((uintptr_t)get_task_map((task_t)pMemNt->Core.u.Lock.R0Process) + s_offPmap);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PgNo = pmap_find_phys(Pmap, (uintptr_t)pMemNt->Core.pv + iPage * PAGE_SIZE);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync AssertReturn(PgNo, NIL_RTHCPHYS);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PhysAddr = (RTHCPHYS)PgNo << PAGE_SHIFT;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync Assert((PhysAddr >> PAGE_SHIFT) == PgNo);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync else
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync#endif /* USE_VM_MAP_WIRE */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * Get the memory descriptor.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync IOMemoryDescriptor *pMemDesc = pMemNt->pMemDesc;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (!pMemDesc)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync pMemDesc = pMemNt->pMemMap->getMemoryDescriptor();
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync AssertReturn(pMemDesc, NIL_RTHCPHYS);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync * If we've got a memory descriptor, use getPhysicalSegment64().
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync addr64_t Addr = pMemDesc->getPhysicalSegment64(iPage * PAGE_SIZE, NULL);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync AssertMsgReturn(Addr, ("iPage=%u\n", iPage), NIL_RTHCPHYS);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync PhysAddr = Addr;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync AssertMsgReturn(PhysAddr == Addr, ("PhysAddr=%VHp Addr=%RX64\n", PhysAddr, (uint64_t)Addr), NIL_RTHCPHYS);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return PhysAddr;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync