GMMR0.cpp revision 6d77ab9a6b06c01a3aaaa3356c580f291466453d
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * GMM - Global Memory Manager.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Copyright (C) 2007 InnoTek Systemberatung GmbH
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * available from http://www.virtualbox.org. This file is free software;
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * you can redistribute it and/or modify it under the terms of the GNU
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * General Public License as published by the Free Software Foundation,
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync/** @page pg_gmm GMM - The Global Memory Manager
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * As the name indicates, this component is responsible for global memory
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * management. Currently only guest RAM is allocated from the GMM, but this
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * may change to include shadow page tables and other bits later.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Guest RAM is managed as individual pages, but allocated from the host OS
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * in chunks for reasons of portability / efficiency. To minimize the memory
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * footprint all tracking structure must be as small as possible without
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * unnecessary performance penalties.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * The allocation chunks has fixed sized, the size defined at compile time
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * by the GMM_CHUNK_SIZE \#define.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Each chunk is given an unquie ID. Each page also has a unique ID. The
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * relation ship between the two IDs is:
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @verbatim
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync (idChunk << GMM_CHUNK_SHIFT) | iPage
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync @endverbatim
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Where GMM_CHUNK_SHIFT is log2(GMM_CHUNK_SIZE / PAGE_SIZE) and iPage is
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * the index of the page within the chunk. This ID scheme permits for efficient
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * chunk and page lookup, but it relies on the chunk size to be set at compile
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * time. The chunks are organized in an AVL tree with their IDs being the keys.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * The physical address of each page in an allocation chunk is maintained by
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * the RTR0MEMOBJ and obtained using RTR0MemObjGetPagePhysAddr. There is no
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * need to duplicate this information (it'll cost 8-bytes per page if we did).
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * So what do we need to track per page? Most importantly we need to know what
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * state the page is in:
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * - Private - Allocated for (eventually) backing one particular VM page.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * - Shared - Readonly page that is used by one or more VMs and treated
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * as COW by PGM.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * - Free - Not used by anyone.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * For the page replacement operations (sharing, defragmenting and freeing)
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * to be somewhat efficient, private pages needs to be associated with a
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * particular page in a particular VM.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Tracking the usage of shared pages is impractical and expensive, so we'll
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * settle for a reference counting system instead.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Free pages will be chained on LIFOs
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * On 64-bit systems we will use a 64-bit bitfield per page, while on 32-bit
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * systems a 32-bit bitfield will have to suffice because of address space
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * limitations. The GMMPAGE structure shows the details.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @section sec_gmm_alloc_strat Page Allocation Strategy
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * The strategy for allocating pages has to take fragmentation and shared
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * pages into account, or we may end up with with 2000 chunks with only
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * a few pages in each. The fragmentation wrt shared pages is that unlike
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * private pages they cannot easily be reallocated. Private pages can be
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * reallocated by a defragmentation thread in the same manner that sharing
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * The first approach is to manage the free pages in two sets depending on
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * whether they are mainly for the allocation of shared or private pages.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * In the initial implementation there will be almost no possibility for
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * mixing shared and private pages in the same chunk (only if we're really
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * stressed on memory), but when we implement forking of VMs and have to
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * deal with lots of COW pages it'll start getting kind of interesting.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * The sets are lists of chunks with approximately the same number of
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * free pages. Say the chunk size is 1MB, meaning 256 pages, and a set
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * consists of 16 lists. So, the first list will contain the chunks with
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * 1-7 free pages, the second covers 8-15, and so on. The chunks will be
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * moved between the lists as pages are freed up or allocated.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @section sec_gmm_costs Costs
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * The per page cost in kernel space is 32-bit plus whatever RTR0MEMOBJ
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * entails. In addition there is the chunk cost of approximately
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * (sizeof(RT0MEMOBJ) + sizof(CHUNK)) / 2^CHUNK_SHIFT bytes per page.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * On Windows the per page RTR0MEMOBJ cost is 32-bit on 32-bit windows
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * and 64-bit on 64-bit windows (a PFN_NUMBER in the MDL). So, 64-bit per page.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * The cost on Linux is identical, but here it's because of sizeof(struct page *).
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @section sec_gmm_legacy Legacy Mode for Non-Tier-1 Platforms
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * In legacy mode the page source is locked user pages and not
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * RTR0MemObjAllocPhysNC, this means that a page can only be allocated
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * by the VM that locked it. We will make no attempt at implementing
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * page sharing on these systems, just do enough to make it all work.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @subsection sub_gmm_locking Serializing
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * One simple fast mutex will be employed in the initial implementation, not
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * two as metioned in @ref subsec_pgmPhys_Serializing.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @see subsec_pgmPhys_Serializing
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * @section sec_gmm_overcommit Memory Over-Commitment Management
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * The GVM will have to do the system wide memory over-commitment
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * management. My current ideas are:
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * - Per VM oc policy that indicates how much to initially commit
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * to it and what to do in a out-of-memory situation.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * - Prevent overtaxing the host.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * There are some challenges here, the main ones are configurability and
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * security. Should we for instance permit anyone to request 100% memory
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * commitment? Who should be allowed to do runtime adjustments of the
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * config. And how to prevent these settings from being lost when the last
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * VM process exits? The solution is probably to have an optional root
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * daemon the will keep VMMR0.r0 in memory and enable the security measures.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * This will not be implemented this week. :-)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/*******************************************************************************
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync* Header Files *
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync*******************************************************************************/
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/*******************************************************************************
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync* Structures and Typedefs *
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync*******************************************************************************/
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** Pointer to set of free chunks. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** Pointer to a GMM allocation chunk. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * The per-page tracking structure employed by the GMM.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * On 32-bit hosts we'll some trickery is necessary to compress all
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * the information into 32-bits. When the fSharedFree member is set,
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * the 30th bit decides whether it's a free page or not.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * Because of the different layout on 32-bit and 64-bit hosts, macros
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync * are used to get and set some of the data.
81f46059436c6145937a4cc2c7424023a289fcd8vboxsynctypedef union GMMPAGE
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /** Unsigned integer view. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /** The common view. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /** The page state. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /** The view of a private page. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /** The guest page frame number. (Max addressable: 2 ^ 44 - 16) */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /** The GVM handle. (64K VMs) */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /** Reserved. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /** The page state. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The view of a shared page. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The reference count. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** Reserved. Checksum or something? Two hGVMs for forking? */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The page state. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The view of a free page. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The index of the next page in the free list. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** Reserved. Checksum or something? */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The page state. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#else /* 32-bit */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** Unsigned integer view. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The common view. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The page state. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The view of a private page. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The guest page frame number. (Max addressable: 2 ^ 36) */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The GVM handle. (127 VMs) */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The top page state bit, MBZ. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The view of a shared page. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The reference count. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The page state. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The view of a free page. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The index of the next page in the free list. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The page state. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** Pointer to a GMMPAGE. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** @name The Page States.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** A private page. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** A private page - alternative value used on the 32-bit implemenation.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * This will never be used on 64-bit hosts. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** A shared page. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** A free page. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** @def GMM_PAGE_IS_PRIVATE
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @returns true if free, false if not.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @param pPage The GMM page.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync# define GMM_PAGE_IS_PRIVATE(pPage) ( (pPage)->Common.u2State == GMM_PAGE_STATE_PRIVATE )
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync# define GMM_PAGE_IS_PRIVATE(pPage) ( (pPage)->Private.fZero == 0 )
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** @def GMM_PAGE_IS_FREE
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @returns true if free, false if not.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @param pPage The GMM page.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#define GMM_PAGE_IS_SHARED(pPage) ( (pPage)->Common.u2State == GMM_PAGE_STATE_SHARED )
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** @def GMM_PAGE_IS_FREE
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @returns true if free, false if not.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @param pPage The GMM page.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync#define GMM_PAGE_IS_FREE(pPage) ( (pPage)->Common.u2State == GMM_PAGE_STATE_FREE )
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** @def GMM_PAGE_PFN_END
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * The end of the the valid guest pfn range, {0..GMM_PAGE_PFN_END-1}.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * @remark Some of the values outside the range has special meaning, see related \#defines.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** @def GMM_PAGE_PFN_UNSHAREABLE
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Indicates that this page isn't used for normal guest memory and thus isn't shareable.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync# define GMM_PAGE_PFN_UNSHAREABLE UINT32_C(0xfffffff1)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync# define GMM_PAGE_PFN_UNSHAREABLE UINT32_C(0x00fffff1)
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** @def GMM_GCPHYS_END
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * The end of the valid guest physical address as it applies to GMM pages.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * This must reflect the constraints imposed by the RTGCPHYS type and
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * the guest page frame number used internally in GMMPAGE. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * A GMM allocation chunk ring-3 mapping record.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * This should really be associated with a session and not a VM, but
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * it's simpler to associated with a VM and cleanup with the VM object
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * is destroyed.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsynctypedef struct GMMCHUNKMAP
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The mapping object. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The VM owning the mapping. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync/** Pointer to a GMM allocation chunk mapping. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * A GMM allocation chunk.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsynctypedef struct GMMCHUNK
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The AVL node core.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * The Key is the chunk ID. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The memory object.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * Either from RTR0MemObjAllocPhysNC or RTR0MemObjLockUser depending on
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * what the host can dish up with. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** Pointer to the next chunk in the free list. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** Pointer to the previous chunk in the free list. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** Pointer to the free set this chunk belongs to. NULL for
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * chunks with no free pages. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** Pointer to an array of mappings. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The number of mappings. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The head of the list of free pages. UINT16_MAX is the NIL value. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The number of free pages. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The GVM handle of the VM that first allocated pages from this chunk, this
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * is used as a preference when there are several chunks to choose from.
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync * When in legacy mode this isn't a preference any longer. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The number of private pages. */
b8e7a8042499abf6f2551c545f6141b36868ab4dvboxsync /** The number of shared pages. */
81f46059436c6145937a4cc2c7424023a289fcd8vboxsync /** Reserved for later. */
} GMMCHUNK;
typedef struct GMMCHUNKTLBE
} GMMCHUNKTLBE;
typedef struct GMMCHUNKTLB
} GMMCHUNKTLB;
typedef struct GMMCHUNKFREESET
typedef struct GMM
bool fLegacyMode;
} GMM;
if (!pGMM)
return VERR_NO_MEMORY;
return VINF_SUCCESS;
return rc;
else if (0)//pGVM->gmm.s.cPrivatePages)
RTAvlU32DoWithAll(&pGMM->pChunks, true /* fFromLeft */, gmmR0FreeVMPagesInChunk, (void *)pGVM->hSelf);
// pGVM->gmm.s.cBasePages = 0;
// pGVM->gmm.s.cPrivatePages = 0;
// pGVM->gmm.s.cSharedPages = 0;
#ifndef VBOx_STRICT
unsigned cPrivate = 0;
unsigned cShared = 0;
unsigned cFree = 0;
while (iPage-- > 0)
cFree++;
cPrivate++;
cFree++;
cShared++;
GMMR0DECL(int) GMMR0InitialReservation(PVM pVM, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages,
LogFlow(("GMMR0InitialReservation: pVM=%p cBasePages=%#llx cShadowPages=%#x cFixedPages=%#x enmPolicy=%d enmPriority=%d\n",
if (!pGVM)
return VERR_INVALID_PARAMETER;
return VERR_NOT_OWNER;
AssertReturn(enmPolicy > GMMOCPOLICY_INVALID && enmPolicy < GMMOCPOLICY_END, VERR_INVALID_PARAMETER);
AssertReturn(enmPriority > GMMPRIORITY_INVALID && enmPriority < GMMPRIORITY_END, VERR_INVALID_PARAMETER);
return rc;
AssertMsgReturn(pReq->Hdr.cbReq != sizeof(*pReq), ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(*pReq)), VERR_INVALID_PARAMETER);
return GMMR0InitialReservation(pVM, pReq->cBasePages, pReq->cShadowPages, pReq->cFixedPages, pReq->enmPolicy, pReq->enmPriority);
GMMR0DECL(int) GMMR0UpdateReservation(PVM pVM, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages)
if (!pGVM)
return VERR_INVALID_PARAMETER;
return VERR_NOT_OWNER;
return rc;
AssertMsgReturn(pReq->Hdr.cbReq != sizeof(*pReq), ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(*pReq)), VERR_INVALID_PARAMETER);
return NULL;
return NULL;
if (pPrev)
if (pNext)
return idChunk;
AssertMsgReturn(!ASMAtomicBitTestAndSet(&pGMM->bmChunkId[0], idChunk), ("%d\n", idChunk), NIL_GVM_HANDLE);
pPage->u = 0;
return rc;
if (pChunk)
return VINF_SUCCESS;
return rc;
if (!pChunk)
return rc;
return VINF_SUCCESS;
pPage->u = 0;
static int gmmR0AllocatePages(PGMM pGMM, PGVM pGVM, uint32_t cPages, PGMMPAGEDESC paPages, GMMACCOUNT enmAccount)
return VERR_GMM_HIT_GLOBAL_LIMIT;
switch (enmAccount)
case GMMACCOUNT_BASE:
return VERR_GMM_HIT_VM_ACCOUNT_LIMIT;
case GMMACCOUNT_SHADOW:
return VERR_GMM_HIT_VM_ACCOUNT_LIMIT;
case GMMACCOUNT_FIXED:
return VERR_GMM_HIT_VM_ACCOUNT_LIMIT;
return VERR_GMM_SEED_ME;
return rc;
return VERR_GMM_SEED_ME;
switch (enmAccount)
return VINF_SUCCESS;
GMMR0DECL(int) GMMR0AllocateHandyPages(PVM pVM, uint32_t cPagesToUpdate, uint32_t cPagesToAlloc, PGMMPAGEDESC paPages)
return VERR_INVALID_PARAMETER;
return VERR_NOT_OWNER;
unsigned iPage = 0;
AssertMsgReturn(paPages[iPage].HCPhysGCPhys == NIL_RTHCPHYS, ("#%#x: %RHp\n", iPage, paPages[iPage].HCPhysGCPhys), VERR_INVALID_PARAMETER);
AssertMsgReturn(paPages[iPage].idPage == NIL_GMM_PAGEID, ("#%#x: %#x\n", iPage, paPages[iPage].idPage), VERR_INVALID_PARAMETER);
AssertMsgReturn(paPages[iPage].idSharedPage == NIL_GMM_PAGEID, ("#%#x: %#x\n", iPage, paPages[iPage].idSharedPage), VERR_INVALID_PARAMETER);
return rc;
GMMR0DECL(int) GMMR0AllocatePages(PVM pVM, uint32_t cPages, PGMMPAGEDESC paPages, GMMACCOUNT enmAccount)
LogFlow(("GMMR0AllocatePages: pVM=%p cPages=%#x paPages=%p enmAccount=%d\n", pVM, cPages, paPages, enmAccount));
if (!pGVM)
return VERR_INVALID_PARAMETER;
return VERR_NOT_OWNER;
AssertMsgReturn(enmAccount > GMMACCOUNT_INVALID && enmAccount < GMMACCOUNT_END, ("%d\n", enmAccount), VERR_INVALID_PARAMETER);
AssertMsgReturn(cPages > 0 && cPages < RT_BIT(32 - PAGE_SHIFT), ("%#x\n", cPages), VERR_INVALID_PARAMETER);
AssertMsgReturn(paPages[iPage].idPage == NIL_GMM_PAGEID, ("#%#x: %#x\n", iPage, paPages[iPage].idPage), VERR_INVALID_PARAMETER);
AssertMsgReturn(paPages[iPage].idSharedPage == NIL_GMM_PAGEID, ("#%#x: %#x\n", iPage, paPages[iPage].idSharedPage), VERR_INVALID_PARAMETER);
return rc;
GMMR0DECL(int) GMMR0FreePages(PVM pVM, uint32_t cPages, PGMMFREEPAGEDESC paPages, GMMACCOUNT enmAccount)
return VERR_NOT_IMPLEMENTED;
GMMR0DECL(int) GMMR0BalloonedPages(PVM pVM, uint32_t cBalloonedPages, uint32_t cPagesToFree, PGMMFREEPAGEDESC paPages)
return VERR_NOT_IMPLEMENTED;
GMMR0DECL(int) GMMR0FreeMapUnmapChunk(PVM pVM, uint32_t idChunkMap, uint32_t idChunkUnmap, PRTR3PTR pvR3)
return VERR_NOT_IMPLEMENTED;
AssertMsgReturn(pReq->Hdr.cbReq == sizeof(*pReq), ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(*pReq)), VERR_INVALID_PARAMETER);
return VERR_NOT_IMPLEMENTED;