memobj-r0drv-nt.cpp revision 08716b8e14a05ff56ac7e616f311310baed06248
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/* $Id$ */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/** @file
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync * IPRT - Ring-0 Memory Objects, NT.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync/*
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * The contents of this file may alternatively be used under the terms
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * of the Common Development and Distribution License Version 1.0
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution, in which case the provisions of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * CDDL are applicable instead of those of the GPL.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync *
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * You may elect to license modified versions of this file under the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * terms and conditions of either the GPL or the CDDL or both.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync *
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * additional information or have any questions.
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;
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync#endif
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync /** Pointer returned by MmSecureVirtualMemory */
66fcb39649c3b5ba2787165459f2e357ed1638edvboxsync PVOID pvSecureMem;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /** The number of PMDLs (memory descriptor lists) in the array. */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync uint32_t 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:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync#ifndef 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;
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync if (pMemNt->pvSecureMem)
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync {
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync MmUnsecureVirtualMemory(pMemNt->pvSecureMem);
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync pMemNt->pvSecureMem = NULL;
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmFreePagesFromMdl(pMemNt->apMdls[0]);
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync ExFreePool(pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 0;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync break;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#endif
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync AssertFailed();
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync break;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
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:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync#ifndef IPRT_TARGET_NT4
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMemNt->fAllocatedPagesForMdl)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmFreePagesFromMdl(pMemNt->apMdls[0]);
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync ExFreePool(pMemNt->apMdls[0]);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->apMdls[0] = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->cMdls = 0;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync break;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#endif
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync AssertFailed();
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync break;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync case RTR0MEMOBJTYPE_LOCK:
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync if (pMemNt->pvSecureMem)
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync {
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync MmUnsecureVirtualMemory(pMemNt->pvSecureMem);
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync pMemNt->pvSecureMem = NULL;
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync }
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync for (uint32_t i = 0; i < pMemNt->cMdls; i++)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync MmUnlockPages(pMemNt->apMdls[i]);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync IoFreeMdl(pMemNt->apMdls[i]);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync pMemNt->apMdls[i] = NULL;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync break;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync case RTR0MEMOBJTYPE_RES_VIRT:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync/* if (pMemNt->Core.u.ResVirt.R0Process == NIL_RTR0PROCESS)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync }
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync else
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync }*/
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync AssertMsgFailed(("RTR0MEMOBJTYPE_RES_VIRT\n"));
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VERR_INTERNAL_ERROR;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync break;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync case RTR0MEMOBJTYPE_MAPPING:
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
3a4ad4e6a194c6595d929ddff249e11c787a5085vboxsync Assert(pMemNt->cMdls == 0 && pMemNt->Core.pv);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PRTR0MEMOBJNT pMemNtParent = (PRTR0MEMOBJNT)pMemNt->Core.uRel.Child.pParent;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Assert(pMemNtParent);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (pMemNtParent->cMdls)
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync Assert(pMemNtParent->cMdls == 1 && pMemNtParent->apMdls[0]);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync Assert( pMemNt->Core.u.Mapping.R0Process == NIL_RTR0PROCESS
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync || pMemNt->Core.u.Mapping.R0Process == RTR0ProcHandleSelf());
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync MmUnmapLockedPages(pMemNt->Core.pv, pMemNtParent->apMdls[0]);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync }
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync else
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync Assert( pMemNtParent->Core.enmType == RTR0MEMOBJTYPE_PHYS
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync && !pMemNtParent->Core.u.Phys.fAllocated);
3a4ad4e6a194c6595d929ddff249e11c787a5085vboxsync Assert(pMemNt->Core.u.Mapping.R0Process == NIL_RTR0PROCESS);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync MmUnmapIoSpace(pMemNt->Core.pv, pMemNt->Core.cb);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync }
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{
a763a20b1d06570dc0bd7588050772baf0d34f01vboxsync AssertMsgReturn(cb <= _1G, ("%#x\n", cb), VERR_OUT_OF_RANGE); /* for safe size_t -> ULONG */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
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 {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PMDL pMdl = IoAllocateMdl(pv, (ULONG)cb, FALSE, FALSE, NULL);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMdl)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmBuildMdlForNonPagedPool(pMdl);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync#ifdef RT_ARCH_AMD64
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync MmProtectMdlSystemAddress(pMdl, PAGE_EXECUTE_READWRITE);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync#endif
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{
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync AssertMsgReturn(cb <= _1G, ("%#x\n", cb), VERR_OUT_OF_RANGE); /* for safe size_t -> ULONG */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
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 Zero.QuadPart = 0;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PHYSICAL_ADDRESS HighAddr;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync HighAddr.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 {
d0e01ab906aceaf4c7110127efb0ad71b9037e12vboxsync NTSTATUS rcNt = GetExceptionCode();
d0e01ab906aceaf4c7110127efb0ad71b9037e12vboxsync Log(("rtR0MemObjNativeAllocLow: Exception Code %#x\n", rcNt));
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /* nothing */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync MmFreePagesFromMdl(pMdl);
547d46bba272294fddc7601967690c9350914527vboxsync ExFreePool(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.
041d531fb5794a8a4cf6c35886d89ec25cbbdde2vboxsync * @param uAlignment The alignment of the physical memory to allocate.
041d531fb5794a8a4cf6c35886d89ec25cbbdde2vboxsync * Supported values are 0 (alias for PAGE_SIZE), PAGE_SIZE, _2M, _4M and _1G.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync */
041d531fb5794a8a4cf6c35886d89ec25cbbdde2vboxsyncstatic int rtR0MemObjNativeAllocContEx(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable, RTHCPHYS PhysHighest, size_t uAlignment)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync AssertMsgReturn(cb <= _1G, ("%#x\n", cb), VERR_OUT_OF_RANGE); /* for safe size_t -> ULONG */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Allocate the memory and create an MDL for it.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
33c2ec656619b35b0b14b6379f8213a5a7eb1f98vboxsync PHYSICAL_ADDRESS PhysAddrHighest, PhysAddrLowest, PhysAddrBoundary;
33c2ec656619b35b0b14b6379f8213a5a7eb1f98vboxsync PhysAddrHighest.QuadPart = PhysHighest;
33c2ec656619b35b0b14b6379f8213a5a7eb1f98vboxsync PhysAddrLowest.QuadPart = 0;
7b226b12c7ae1630222afbad3ace52859535d2d7vboxsync PhysAddrBoundary.QuadPart = (uAlignment == PAGE_SIZE) ? 0 : uAlignment;
33c2ec656619b35b0b14b6379f8213a5a7eb1f98vboxsync void *pv = MmAllocateContiguousMemorySpecifyCache(cb, PhysAddrLowest, PhysAddrHighest, PhysAddrBoundary, MmCached);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (!pv)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync return VERR_NO_MEMORY;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PMDL pMdl = IoAllocateMdl(pv, (ULONG)cb, FALSE, FALSE, NULL);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMdl)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync MmBuildMdlForNonPagedPool(pMdl);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync#ifdef RT_ARCH_AMD64
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync MmProtectMdlSystemAddress(pMdl, PAGE_EXECUTE_READWRITE);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync#endif
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{
041d531fb5794a8a4cf6c35886d89ec25cbbdde2vboxsync return rtR0MemObjNativeAllocContEx(ppMem, cb, fExecutable, _4G-1, PAGE_SIZE /* alignment */);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
041d531fb5794a8a4cf6c35886d89ec25cbbdde2vboxsyncint rtR0MemObjNativeAllocPhys(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#ifndef IPRT_TARGET_NT4
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Try and see if we're lucky and get a contiguous chunk from MmAllocatePagesForMdl.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync *
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * This is preferable to using MmAllocateContiguousMemory because there are
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * a few situations where the memory shouldn't be mapped, like for instance
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * VT-x control memory. Since these are rather small allocations (one or
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * two pages) MmAllocatePagesForMdl will probably be able to satisfy the
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * request.
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync *
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * If the allocation is big, the chances are *probably* not very good. The
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * current limit is kind of random...
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
08716b8e14a05ff56ac7e616f311310baed06248vboxsync if (cb < _128K
08716b8e14a05ff56ac7e616f311310baed06248vboxsync && (uAlignment == 0 || uAlignment == PAGE_SIZE))
08716b8e14a05ff56ac7e616f311310baed06248vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PHYSICAL_ADDRESS Zero;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Zero.QuadPart = 0;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PHYSICAL_ADDRESS HighAddr;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync HighAddr.QuadPart = PhysHighest == NIL_RTHCPHYS ? MAXLONGLONG : PhysHighest;
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;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync const size_t cPages = cb >> PAGE_SHIFT;
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 }
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync MmFreePagesFromMdl(pMdl);
547d46bba272294fddc7601967690c9350914527vboxsync ExFreePool(pMdl);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync#endif /* !IPRT_TARGET_NT4 */
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync
041d531fb5794a8a4cf6c35886d89ec25cbbdde2vboxsync return rtR0MemObjNativeAllocContEx(ppMem, cb, false, PhysHighest, uAlignment);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
c5d2523548cc57504b829f53f1362b848a84542cvboxsyncint rtR0MemObjNativeAllocPhysNC(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, RTHCPHYS PhysHighest)
c5d2523548cc57504b829f53f1362b848a84542cvboxsync{
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync#ifndef IPRT_TARGET_NT4
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PHYSICAL_ADDRESS Zero;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync Zero.QuadPart = 0;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PHYSICAL_ADDRESS HighAddr;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync HighAddr.QuadPart = PhysHighest == NIL_RTHCPHYS ? MAXLONGLONG : PhysHighest;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PMDL pMdl = MmAllocatePagesForMdl(Zero, HighAddr, Zero, cb);
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (pMdl)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync if (MmGetMdlByteCount(pMdl) >= cb)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_PHYS_NC, NULL, 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);
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync ExFreePool(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 */
a62a05e79ff09a38cb8f25c947f9ae8b89ed220evboxsync PFN_NUMBER Pfn = (PFN_NUMBER)(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 {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync pMemNt->Core.u.Phys.PhysBase = Phys;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync pMemNt->Core.u.Phys.fAllocated = false;
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 *
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync * @param ppMem Where to store the memory object pointer.
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync * @param pv First page.
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync * @param cb Number of bytes.
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync * @param fAccess The desired access, a combination of RTMEM_PROT_READ
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync * and RTMEM_PROT_WRITE.
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync * @param R0Process The process \a pv and \a cb refers to.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
db3d025f28c59aececbbda4174fa513496c89b2bvboxsyncstatic int rtR0MemObjNtLock(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync /*
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync * Calc the number of MDLs we need and allocate the memory object structure.
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync size_t cMdls = cb / MAX_LOCK_MEM_SIZE;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (cb % MAX_LOCK_MEM_SIZE)
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync cMdls++;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (cMdls >= UINT32_MAX)
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return VERR_OUT_OF_RANGE;
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(RT_OFFSETOF(RTR0MEMOBJNT, apMdls[cMdls]),
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync RTR0MEMOBJTYPE_LOCK, pv, 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;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync uint8_t *pb = (uint8_t *)pv;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync uint32_t 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"));
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PMDL pMdl = IoAllocateMdl(pb, (ULONG)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 {
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync MmProbeAndLockPages(pMdl,
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync R0Process == NIL_RTR0PROCESS ? KernelMode : UserMode,
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync fAccess == RTMEM_PROT_READ
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync ? IoReadAccess
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync : fAccess == RTMEM_PROT_WRITE
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync ? IoWriteAccess
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync : IoModifyAccess);
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync
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 }
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync if (R0Process != NIL_RTR0PROCESS)
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync {
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync /* Make sure the user process can't change the allocation. */
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync pMemNt->pvSecureMem = MmSecureVirtualMemory(pv, cb,
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync fAccess & RTMEM_PROT_WRITE
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync ? PAGE_READWRITE
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync : PAGE_READONLY);
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync if (!pMemNt->pvSecureMem)
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync {
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync rc = VERR_NO_MEMORY;
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync break;
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync }
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync }
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 {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync MmUnlockPages(pMemNt->apMdls[iMdl]);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync IoFreeMdl(pMemNt->apMdls[iMdl]);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync pMemNt->apMdls[iMdl] = NULL;
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync }
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync if (pMemNt->pvSecureMem)
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync {
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync MmUnsecureVirtualMemory(pMemNt->pvSecureMem);
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync pMemNt->pvSecureMem = NULL;
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync }
66fcb39649c3b5ba2787165459f2e357ed1638edvboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync rtR0MemObjDelete(&pMemNt->Core);
66fcb39649c3b5ba2787165459f2e357ed1638edvboxsync return rc;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
db3d025f28c59aececbbda4174fa513496c89b2bvboxsyncint rtR0MemObjNativeLockUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
e5f6ad85110ebdc7256808a0a3a8ce330370be6avboxsync AssertMsgReturn(R0Process == RTR0ProcHandleSelf(), ("%p != %p\n", R0Process, RTR0ProcHandleSelf()), VERR_NOT_SUPPORTED);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync /* (Can use MmProbeAndLockProcessPages if we need to mess with other processes later.) */
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync return rtR0MemObjNtLock(ppMem, (void *)R3Ptr, cb, fAccess, R0Process);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
db3d025f28c59aececbbda4174fa513496c89b2bvboxsyncint rtR0MemObjNativeLockKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pv, size_t cb, uint32_t fAccess)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
db3d025f28c59aececbbda4174fa513496c89b2bvboxsync return rtR0MemObjNtLock(ppMem, pv, cb, fAccess, NIL_RTR0PROCESS);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsyncint rtR0MemObjNativeReserveKernel(PPRTR0MEMOBJINTERNAL ppMem, void *pvFixed, size_t cb, size_t uAlignment)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
60680e89b1c6689e75730c2588af97b788f21dd0vboxsync /*
60680e89b1c6689e75730c2588af97b788f21dd0vboxsync * MmCreateSection(SEC_RESERVE) + MmMapViewInSystemSpace perhaps?
60680e89b1c6689e75730c2588af97b788f21dd0vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VERR_NOT_IMPLEMENTED;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
c5d2523548cc57504b829f53f1362b848a84542cvboxsyncint rtR0MemObjNativeReserveUser(PPRTR0MEMOBJINTERNAL ppMem, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
60680e89b1c6689e75730c2588af97b788f21dd0vboxsync /*
60680e89b1c6689e75730c2588af97b788f21dd0vboxsync * ZeCreateSection(SEC_RESERVE) + ZwMapViewOfSection perhaps?
60680e89b1c6689e75730c2588af97b788f21dd0vboxsync */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return VERR_NOT_IMPLEMENTED;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
60680e89b1c6689e75730c2588af97b788f21dd0vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync/**
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * Internal worker for rtR0MemObjNativeMapKernel and rtR0MemObjNativeMapUser.
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync *
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * @returns IPRT status code.
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * @param ppMem Where to store the memory object for the mapping.
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * @param pMemToMap The memory object to map.
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * @param pvFixed Where to map it. (void *)-1 if anywhere is fine.
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * @param uAlignment The alignment requirement for the mapping.
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * @param fProt The desired page protection for the mapping.
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * @param R0Process If NIL_RTR0PROCESS map into system (kernel) memory.
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * If not nil, it's the current process.
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsyncstatic int rtR0MemObjNtMap(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync unsigned fProt, RTR0PROCESS R0Process)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync int rc = VERR_MAP_FAILED;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
ad1e35f9fb71d147c2126449a25adf0f8e155aaavboxsync /*
ad1e35f9fb71d147c2126449a25adf0f8e155aaavboxsync * Check that the specified alignment is supported.
ad1e35f9fb71d147c2126449a25adf0f8e155aaavboxsync */
ad1e35f9fb71d147c2126449a25adf0f8e155aaavboxsync if (uAlignment > PAGE_SIZE)
ad1e35f9fb71d147c2126449a25adf0f8e155aaavboxsync return VERR_NOT_SUPPORTED;
ad1e35f9fb71d147c2126449a25adf0f8e155aaavboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync /*
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * There are two basic cases here, either we've got an MDL and can
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * map it using MmMapLockedPages, or we've got a contiguous physical
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync * range (MMIO most likely) and can use MmMapIoSpace.
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PRTR0MEMOBJNT pMemNtToMap = (PRTR0MEMOBJNT)pMemToMap;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (pMemNtToMap->cMdls)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync /* don't attempt map locked regions with more than one mdl. */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (pMemNtToMap->cMdls != 1)
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return VERR_NOT_SUPPORTED;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync#ifdef IPRT_TARGET_NT4
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync /* NT SP0 can't map to a specific address. */
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync if (pvFixed != (void *)-1)
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync return VERR_NOT_SUPPORTED;
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync#endif
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync /* we can't map anything to the first page, sorry. */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (pvFixed == 0)
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return VERR_NOT_SUPPORTED;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync /* only one system mapping for now - no time to figure out MDL restrictions right now. */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if ( pMemNtToMap->Core.uRel.Parent.cMappings
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync && R0Process == NIL_RTR0PROCESS)
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return VERR_NOT_SUPPORTED;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync __try
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync /** @todo uAlignment */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync /** @todo How to set the protection on the pages? */
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync#ifdef IPRT_TARGET_NT4
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync void *pv = MmMapLockedPages(pMemNtToMap->apMdls[0],
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync R0Process == NIL_RTR0PROCESS ? KernelMode : UserMode);
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync#else
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync void *pv = MmMapLockedPagesSpecifyCache(pMemNtToMap->apMdls[0],
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync R0Process == NIL_RTR0PROCESS ? KernelMode : UserMode,
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync MmCached,
3a4ad4e6a194c6595d929ddff249e11c787a5085vboxsync pvFixed != (void *)-1 ? pvFixed : NULL,
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync FALSE /* no bug check on failure */,
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync NormalPagePriority);
d21c2482293dc974a916ea907b85b6d71fc28b06vboxsync#endif
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (pv)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync NOREF(fProt);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_MAPPING, pv,
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync pMemNtToMap->Core.cb);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync if (pMemNt)
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync pMemNt->Core.u.Mapping.R0Process = R0Process;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync *ppMem = &pMemNt->Core;
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync return VINF_SUCCESS;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync rc = VERR_NO_MEMORY;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync MmUnmapLockedPages(pv, pMemNtToMap->apMdls[0]);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync __except(EXCEPTION_EXECUTE_HANDLER)
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync {
d0e01ab906aceaf4c7110127efb0ad71b9037e12vboxsync NTSTATUS rcNt = GetExceptionCode();
d0e01ab906aceaf4c7110127efb0ad71b9037e12vboxsync Log(("rtR0MemObjNtMap: Exception Code %#x\n", rcNt));
d0e01ab906aceaf4c7110127efb0ad71b9037e12vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync /* nothing */
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync rc = VERR_MAP_FAILED;
44bb1f16ce587f939ae4479fbaab6f3bd6de5835vboxsync }
66fcb39649c3b5ba2787165459f2e357ed1638edvboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync else
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync AssertReturn( pMemNtToMap->Core.enmType == RTR0MEMOBJTYPE_PHYS
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync && !pMemNtToMap->Core.u.Phys.fAllocated, VERR_INTERNAL_ERROR);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync /* cannot map phys mem to user space (yet). */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (R0Process != NIL_RTR0PROCESS)
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return VERR_NOT_SUPPORTED;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync /** @todo uAlignment */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync /** @todo How to set the protection on the pages? */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PHYSICAL_ADDRESS Phys;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync Phys.QuadPart = pMemNtToMap->Core.u.Phys.PhysBase;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync void *pv = MmMapIoSpace(Phys, pMemNtToMap->Core.cb, MmCached); /** @todo add cache type to fProt. */
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (pv)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)rtR0MemObjNew(sizeof(*pMemNt), RTR0MEMOBJTYPE_MAPPING, pv,
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync pMemNtToMap->Core.cb);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (pMemNt)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync pMemNt->Core.u.Mapping.R0Process = R0Process;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync *ppMem = &pMemNt->Core;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return VINF_SUCCESS;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync rc = VERR_NO_MEMORY;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync MmUnmapIoSpace(pv, pMemNtToMap->Core.cb);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync NOREF(uAlignment); NOREF(fProt);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync return rc;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
fbb3513a43135c633f7f51544c4bdfce748929bfvboxsyncint rtR0MemObjNativeMapKernel(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, void *pvFixed, size_t uAlignment,
fbb3513a43135c633f7f51544c4bdfce748929bfvboxsync unsigned fProt, size_t offSub, size_t cbSub)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync{
fbb3513a43135c633f7f51544c4bdfce748929bfvboxsync AssertMsgReturn(!offSub && !cbSub, ("%#x %#x\n", offSub, cbSub), VERR_NOT_SUPPORTED);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return rtR0MemObjNtMap(ppMem, pMemToMap, pvFixed, uAlignment, fProt, NIL_RTR0PROCESS);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsyncint rtR0MemObjNativeMapUser(PPRTR0MEMOBJINTERNAL ppMem, RTR0MEMOBJ pMemToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process)
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync{
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync AssertReturn(R0Process == RTR0ProcHandleSelf(), VERR_NOT_SUPPORTED);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return rtR0MemObjNtMap(ppMem, pMemToMap, (void *)R3PtrFixed, uAlignment, fProt, R0Process);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync}
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
31cda52093d58f5c604589fa74949c5fddcbde70vboxsyncint rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt)
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync{
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync NOREF(pMem);
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync NOREF(offSub);
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync NOREF(cbSub);
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync NOREF(fProt);
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync return VERR_NOT_SUPPORTED;
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync}
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync
31cda52093d58f5c604589fa74949c5fddcbde70vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsyncRTHCPHYS rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage)
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync{
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)pMem;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (pMemNt->cMdls)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync if (pMemNt->cMdls == 1)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PPFN_NUMBER paPfns = MmGetMdlPfnArray(pMemNt->apMdls[0]);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return (RTHCPHYS)paPfns[iPage] << PAGE_SHIFT;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync size_t iMdl = iPage / (MAX_LOCK_MEM_SIZE >> PAGE_SHIFT);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync size_t iMdlPfn = iPage % (MAX_LOCK_MEM_SIZE >> PAGE_SHIFT);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync PPFN_NUMBER paPfns = MmGetMdlPfnArray(pMemNt->apMdls[iMdl]);
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return (RTHCPHYS)paPfns[iMdlPfn] << PAGE_SHIFT;
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync }
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync switch (pMemNt->Core.enmType)
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync {
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync case RTR0MEMOBJTYPE_MAPPING:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return rtR0MemObjNativeGetPagePhysAddr(pMemNt->Core.uRel.Child.pParent, iPage);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync case RTR0MEMOBJTYPE_PHYS:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return pMemNt->Core.u.Phys.PhysBase + (iPage << PAGE_SHIFT);
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync case RTR0MEMOBJTYPE_PAGE:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync case RTR0MEMOBJTYPE_PHYS_NC:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync case RTR0MEMOBJTYPE_LOW:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync case RTR0MEMOBJTYPE_CONT:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync case RTR0MEMOBJTYPE_LOCK:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync default:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync AssertMsgFailed(("%d\n", pMemNt->Core.enmType));
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync case RTR0MEMOBJTYPE_RES_VIRT:
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync return NIL_RTHCPHYS;
d534750e38f9bab40fd4ab06d176fea25ec91c44vboxsync }
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync}
e5bfc5c34142a7550be3564a8e01a037b1db5b31vboxsync