MMHyper.cpp revision fb5e37303b228a79c05cabfce2fe0fedfe32ed8a
8d43244aa3d322f7807a4b0488f1038dd2595dc1vboxsync/* $Id$ */
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync/** @file
682a27d94b9116c719038882487b99053985f91avboxsync * MM - Memory Monitor(/Manager) - Hypervisor Memory Area.
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync */
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006 InnoTek Systemberatung GmbH
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync *
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * available from http://www.virtualbox.org. This file is free software;
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * you can redistribute it and/or modify it under the terms of the GNU
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * General Public License as published by the Free Software Foundation,
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync *
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * If you received this file as part of a commercial VirtualBox
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * distribution, then only the terms of your commercial VirtualBox
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * license agreement apply instead of the previous paragraph.
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync */
682a27d94b9116c719038882487b99053985f91avboxsync
b8f36a8f77f0140f48170d5b3cd9ee9ea1c14294vboxsync
8d43244aa3d322f7807a4b0488f1038dd2595dc1vboxsync
682a27d94b9116c719038882487b99053985f91avboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/*******************************************************************************
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync* Header Files *
682a27d94b9116c719038882487b99053985f91avboxsync*******************************************************************************/
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync#define LOG_GROUP LOG_GROUP_MM_HYPER
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync#include <VBox/pgm.h>
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#include <VBox/mm.h>
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync#include <VBox/dbgf.h>
682a27d94b9116c719038882487b99053985f91avboxsync#include "MMInternal.h"
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#include <VBox/vm.h>
682a27d94b9116c719038882487b99053985f91avboxsync#include <VBox/err.h>
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#include <VBox/param.h>
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#include <VBox/log.h>
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#include <iprt/alloc.h>
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync#include <iprt/assert.h>
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync#include <iprt/string.h>
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync/*******************************************************************************
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync* Internal Functions *
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync*******************************************************************************/
c785dbab313731d1f4662b4684c0808cc14703dbvboxsyncstatic DECLCALLBACK(bool) mmR3HyperRelocateCallback(PVM pVM, RTGCPTR GCPtrOld, RTGCPTR GCPtrNew, PGMRELOCATECALL enmMode, void *pvUser);
c785dbab313731d1f4662b4684c0808cc14703dbvboxsyncstatic int mmR3HyperMap(PVM pVM, const size_t cb, const char *pszDesc, PRTGCPTR pGCPtr, PMMLOOKUPHYPER *ppLookup);
c785dbab313731d1f4662b4684c0808cc14703dbvboxsyncstatic int mmR3HyperHeapCreate(PVM pVM, const size_t cb, PMMHYPERHEAP *ppHeap);
c785dbab313731d1f4662b4684c0808cc14703dbvboxsyncstatic int mmR3HyperHeapMap(PVM pVM, PMMHYPERHEAP pHeap, PRTGCPTR ppHeapGC);
c785dbab313731d1f4662b4684c0808cc14703dbvboxsyncstatic DECLCALLBACK(void) mmR3HyperInfoHma(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync/**
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * Initializes the hypvervisor related MM stuff without
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * calling down to PGM.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync *
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * PGM is not initialized at this point, PGM relies on
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * the heap to initialize.
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync *
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * @returns VBox status.
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync */
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsyncint mmr3HyperInit(PVM pVM)
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync{
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync LogFlow(("mmr3HyperInit:\n"));
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync /*
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * Decide Hypervisor mapping in the guest context
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * And setup various hypervisor area and heap parameters.
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync */
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync pVM->mm.s.pvHyperAreaGC = (RTGCPTR)MM_HYPER_AREA_ADDRESS;
7525834c8ff7d6665778b83fb9d0585624ee7ae9vboxsync pVM->mm.s.cbHyperArea = MM_HYPER_AREA_MAX_SIZE;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertRelease(RT_ALIGN_T(pVM->mm.s.pvHyperAreaGC, 1 << X86_PD_SHIFT, RTGCPTR) == pVM->mm.s.pvHyperAreaGC);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync Assert(pVM->mm.s.pvHyperAreaGC < 0xff000000);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync uint32_t cbHyperHeap;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = CFGMR3QueryU32(CFGMR3GetChild(CFGMR3GetRoot(pVM), "MM"), "cbHyperHeap", &cbHyperHeap);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (rc == VERR_CFGM_NO_PARENT || rc == VERR_CFGM_VALUE_NOT_FOUND)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cbHyperHeap = 1280*_1K;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync else if (VBOX_FAILURE(rc))
e68e2431dbeeab80792bbd9b1c64a68fc3358d0evboxsync {
f1301dd8b6870b5a25c7dbdd46e0a0671bb62031vboxsync LogRel(("MM/cbHyperHeap query -> %Vrc\n", rc));
f1301dd8b6870b5a25c7dbdd46e0a0671bb62031vboxsync AssertRCReturn(rc, rc);
f1301dd8b6870b5a25c7dbdd46e0a0671bb62031vboxsync }
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync cbHyperHeap = RT_ALIGN_32(cbHyperHeap, PAGE_SIZE);
683bc538c5d6598479b7da2ad464939422d449d6vboxsync
b608f15cba5036182124f1eee68b761535aa6d14vboxsync /*
683bc538c5d6598479b7da2ad464939422d449d6vboxsync * Allocate the hypervisor heap.
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync *
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync * (This must be done before we start adding memory to the
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync * hypervisor static area because lookup records are allocated from it.)
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync */
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync rc = mmR3HyperHeapCreate(pVM, cbHyperHeap, &pVM->mm.s.pHyperHeapHC);
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync if (VBOX_SUCCESS(rc))
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync {
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync /*
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * Make a small head fence to fend of accidental sequential access.
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync */
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync MMR3HyperReserve(pVM, PAGE_SIZE, "fence", NULL);
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync /*
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync * Map the VM structure into the hypervisor space.
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync */
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync rc = MMR3HyperMapHCPhys(pVM, pVM, pVM->HCPhysVM, sizeof(VM), "VM", &pVM->pVMGC);
c448f9b0b8382e4665c9700488002c45a9b3f137vboxsync if (VBOX_SUCCESS(rc))
c448f9b0b8382e4665c9700488002c45a9b3f137vboxsync {
7525834c8ff7d6665778b83fb9d0585624ee7ae9vboxsync /* Reserve a page for fencing. */
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync MMR3HyperReserve(pVM, PAGE_SIZE, "fence", NULL);
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync /*
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync * Map the heap into the hypervisor space.
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync */
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync rc = mmR3HyperHeapMap(pVM, pVM->mm.s.pHyperHeapHC, &pVM->mm.s.pHyperHeapGC);
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync if (VBOX_SUCCESS(rc))
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync {
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync /*
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync * Register info handlers.
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync */
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync DBGFR3InfoRegisterInternal(pVM, "hma", "Show the layout of the Hypervisor Memory Area.", mmR3HyperInfoHma);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync LogFlow(("mmr3HyperInit: returns VINF_SUCCESS\n"));
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync return VINF_SUCCESS;
e68e2431dbeeab80792bbd9b1c64a68fc3358d0evboxsync }
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync /* Caller will do proper cleanup. */
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync }
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync }
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync LogFlow(("mmr3HyperInit: returns %Vrc\n", rc));
4c953c3c459d80bc3e31a0a65a9dc0463f340e6bvboxsync return rc;
e68e2431dbeeab80792bbd9b1c64a68fc3358d0evboxsync}
b83d9b1072dd8491c7ffe37830e8fd10f2dba561vboxsync
f1301dd8b6870b5a25c7dbdd46e0a0671bb62031vboxsync
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync/**
f1301dd8b6870b5a25c7dbdd46e0a0671bb62031vboxsync * Finalizes the HMA mapping.
f1301dd8b6870b5a25c7dbdd46e0a0671bb62031vboxsync *
f1301dd8b6870b5a25c7dbdd46e0a0671bb62031vboxsync * This is called later during init, most (all) HMA allocations should be done
f1301dd8b6870b5a25c7dbdd46e0a0671bb62031vboxsync * by the time this function is called.
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync *
683bc538c5d6598479b7da2ad464939422d449d6vboxsync * @returns VBox status.
b608f15cba5036182124f1eee68b761535aa6d14vboxsync */
b608f15cba5036182124f1eee68b761535aa6d14vboxsyncMMR3DECL(int) MMR3HyperInitFinalize(PVM pVM)
683bc538c5d6598479b7da2ad464939422d449d6vboxsync{
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync LogFlow(("MMR3HyperInitFinalize:\n"));
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync /*
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync * Adjust and create the HMA mapping.
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync */
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync while ((RTINT)pVM->mm.s.offHyperNextStatic + 64*_1K < (RTINT)pVM->mm.s.cbHyperArea - _4M)
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync pVM->mm.s.cbHyperArea -= _4M;
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync int rc = PGMR3MapPT(pVM, pVM->mm.s.pvHyperAreaGC, pVM->mm.s.cbHyperArea,
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync mmR3HyperRelocateCallback, NULL, "Hypervisor Memory Area");
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync if (VBOX_FAILURE(rc))
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync return rc;
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync pVM->mm.s.fPGMInitialized = true;
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync
4b4dcfe69a693fa32dd64da3d9ea88e996ca1bf5vboxsync /*
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync * Do all the delayed mappings.
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync */
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync PMMLOOKUPHYPER pLookup = (PMMLOOKUPHYPER)((uintptr_t)pVM->mm.s.pHyperHeapHC + pVM->mm.s.offLookupHyper);
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync for (;;)
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync {
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync RTGCPTR GCPtr = pVM->mm.s.pvHyperAreaGC + pLookup->off;
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync unsigned cPages = pLookup->cb >> PAGE_SHIFT;
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync switch (pLookup->enmType)
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync {
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync case MMLOOKUPHYPERTYPE_LOCKED:
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync rc = mmr3MapLocked(pVM, pLookup->u.Locked.pLockedMem, GCPtr, 0, cPages, 0);
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync break;
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync case MMLOOKUPHYPERTYPE_HCPHYS:
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync rc = PGMMap(pVM, GCPtr, pLookup->u.HCPhys.HCPhys, pLookup->cb, 0);
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync break;
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync case MMLOOKUPHYPERTYPE_GCPHYS:
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync {
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync const RTGCPHYS GCPhys = pLookup->u.GCPhys.GCPhys;
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync const size_t cb = pLookup->cb;
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync for (unsigned off = 0; off < cb; off += PAGE_SIZE)
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync {
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync RTHCPHYS HCPhys;
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync rc = PGMPhysGCPhys2HCPhys(pVM, GCPhys + off, &HCPhys);
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync if (VBOX_FAILURE(rc))
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync break;
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync rc = PGMMap(pVM, GCPtr + off, HCPhys, PAGE_SIZE, 0);
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync if (VBOX_FAILURE(rc))
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync break;
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync }
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync break;
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync }
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync
c785dbab313731d1f4662b4684c0808cc14703dbvboxsync case MMLOOKUPHYPERTYPE_DYNAMIC:
c448f9b0b8382e4665c9700488002c45a9b3f137vboxsync /* do nothing here since these are either fences or managed by someone else using PGM. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync default:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("enmType=%d\n", pLookup->enmType));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_FAILURE(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("rc=%Vrc cb=%d GCPtr=%VGv enmType=%d pszDesc=%s\n",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync rc, pLookup->cb, pLookup->enmType, pLookup->pszDesc));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* next */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (pLookup->offNext == (int32_t)NIL_OFFSET)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup = (PMMLOOKUPHYPER)((uintptr_t)pLookup + pLookup->offNext);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync LogFlow(("MMR3HyperInitFinalize: returns VINF_SUCCESS\n"));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VINF_SUCCESS;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Callback function which will be called when PGM is trying to find
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * a new location for the mapping.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * The callback is called in two modes, 1) the check mode and 2) the relocate mode.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * In 1) the callback should say if it objects to a suggested new location. If it
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * accepts the new location, it is called again for doing it's relocation.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @returns true if the location is ok.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @returns false if another location should be found.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM The VM handle.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param GCPtrOld The old virtual address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param GCPtrNew The new virtual address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param enmMode Used to indicate the callback mode.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pvUser User argument. Ignored.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @remark The return value is no a failure indicator, it's an acceptance
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * indicator. Relocation can not fail!
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncstatic DECLCALLBACK(bool) mmR3HyperRelocateCallback(PVM pVM, RTGCPTR GCPtrOld, RTGCPTR GCPtrNew, PGMRELOCATECALL enmMode, void *pvUser)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync switch (enmMode)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Verify location - all locations are good for us.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case PGMRELOCATECALL_SUGGEST:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return true;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Execute the relocation.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case PGMRELOCATECALL_RELOCATE:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Accepted!
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync */
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync AssertMsg(GCPtrOld == pVM->mm.s.pvHyperAreaGC, ("GCPtrOld=%#x pVM->mm.s.pvHyperAreaGC=%#x\n", GCPtrOld, pVM->mm.s.pvHyperAreaGC));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync Log(("Relocating the hypervisor from %#x to %#x\n", GCPtrOld, GCPtrNew));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* relocate our selves and the VM structure. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync RTGCINTPTR offDelta = GCPtrNew - GCPtrOld;
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync pVM->pVMGC += offDelta;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVM->mm.s.pvHyperAreaGC += offDelta;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVM->mm.s.pHyperHeapGC += offDelta;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVM->mm.s.pHyperHeapHC->pbHeapGC += offDelta;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVM->mm.s.pHyperHeapHC->pVMGC += pVM->pVMGC;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* relocate the rest. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync VMR3Relocate(pVM, offDelta);
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync return true;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync default:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("Invalid relocation mode %d\n", enmMode));
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return false;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Maps contiguous HC physical memory into the hypervisor region in the GC.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @return VBox status code.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * @param pVM VM handle.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pvHC Host context address of the memory. Must be page aligned!
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param HCPhys Host context physical address of the memory to be mapped. Must be page aligned!
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param cb Size of the memory. Will be rounded up to nearest page.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pszDesc Description.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * @param pGCPtr Where to store the GC address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncMMR3DECL(int) MMR3HyperMapHCPhys(PVM pVM, void *pvHC, RTHCPHYS HCPhys, size_t cb, const char *pszDesc, PRTGCPTR pGCPtr)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync LogFlow(("MMR3HyperMapHCPhys: pvHc=%p HCPhys=%VHp cb=%d pszDesc=%p:{%s} pGCPtr=%p\n", pvHC, HCPhys, (int)cb, pszDesc, pszDesc, pGCPtr));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * Validate input.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertReturn(RT_ALIGN_P(pvHC, PAGE_SIZE) == pvHC, VERR_INVALID_PARAMETER);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertReturn(RT_ALIGN_T(HCPhys, PAGE_SIZE, RTHCPHYS) == HCPhys, VERR_INVALID_PARAMETER);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertReturn(pszDesc && *pszDesc, VERR_INVALID_PARAMETER);
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Add the memory to the hypervisor area.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync uint32_t cbAligned = RT_ALIGN_32(cb, PAGE_SIZE);
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync AssertReturn(cbAligned >= cb, VERR_INVALID_PARAMETER);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync RTGCPTR GCPtr;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync PMMLOOKUPHYPER pLookup;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = mmR3HyperMap(pVM, cbAligned, pszDesc, &GCPtr, &pLookup);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync pLookup->enmType = MMLOOKUPHYPERTYPE_HCPHYS;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->u.HCPhys.pvHC = pvHC;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->u.HCPhys.HCPhys = HCPhys;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * Update the page table.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (pVM->mm.s.fPGMInitialized)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync rc = PGMMap(pVM, GCPtr, HCPhys, cbAligned, 0);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *pGCPtr = GCPtr;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * Maps contiguous GC physical memory into the hypervisor region in the GC.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @return VBox status code.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM VM handle.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * @param GCPhys Guest context physical address of the memory to be mapped. Must be page aligned!
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param cb Size of the memory. Will be rounded up to nearest page.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pszDesc Mapping description.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pGCPtr Where to store the GC address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncMMR3DECL(int) MMR3HyperMapGCPhys(PVM pVM, RTGCPHYS GCPhys, size_t cb, const char *pszDesc, PRTGCPTR pGCPtr)
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync LogFlow(("MMR3HyperMapGCPhys: GCPhys=%VGp cb=%d pszDesc=%p:{%s} pGCPtr=%p\n", GCPhys, (int)cb, pszDesc, pszDesc, pGCPtr));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Validate input.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertReturn(RT_ALIGN_T(GCPhys, PAGE_SIZE, RTGCPHYS) == GCPhys, VERR_INVALID_PARAMETER);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertReturn(pszDesc && *pszDesc, VERR_INVALID_PARAMETER);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Add the memory to the hypervisor area.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync cb = RT_ALIGN_Z(cb, PAGE_SIZE);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync RTGCPTR GCPtr;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync PMMLOOKUPHYPER pLookup;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = mmR3HyperMap(pVM, cb, pszDesc, &GCPtr, &pLookup);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->enmType = MMLOOKUPHYPERTYPE_GCPHYS;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->u.GCPhys.GCPhys = GCPhys;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * Update the page table.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync for (unsigned off = 0; off < cb; off += PAGE_SIZE)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync RTHCPHYS HCPhys;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync rc = PGMPhysGCPhys2HCPhys(pVM, GCPhys + off, &HCPhys);
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync AssertRC(rc);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_FAILURE(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("rc=%Vrc GCPhys=%VGv off=%#x %s\n", rc, GCPhys, off, pszDesc));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (pVM->mm.s.fPGMInitialized)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync rc = PGMMap(pVM, GCPtr + off, HCPhys, PAGE_SIZE, 0);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertRC(rc);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_FAILURE(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("rc=%Vrc GCPhys=%VGv off=%#x %s\n", rc, GCPhys, off, pszDesc));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc) && pGCPtr)
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync *pGCPtr = GCPtr;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Locks and Maps HC virtual memory into the hypervisor region in the GC.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @return VBox status code.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM VM handle.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pvHC Host context address of the memory (may be not page aligned).
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param cb Size of the memory. Will be rounded up to nearest page.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param fFree Set this if MM is responsible for freeing the memory using SUPPageFree.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * @param pszDesc Mapping description.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pGCPtr Where to store the GC address corresponding to pvHC.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncMMR3DECL(int) MMR3HyperMapHCRam(PVM pVM, void *pvHC, size_t cb, bool fFree, const char *pszDesc, PRTGCPTR pGCPtr)
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync LogFlow(("MMR3HyperMapHCRam: pvHc=%p cb=%d fFree=%d pszDesc=%p:{%s} pGCPtr=%p\n", pvHC, (int)cb, fFree, pszDesc, pszDesc, pGCPtr));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Validate input.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if ( !pvHC
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync || cb <= 0
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync || !pszDesc
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync || !*pszDesc)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("Invalid parameter\n"));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VERR_INVALID_PARAMETER;
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Page align address and size.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync void *pvHCPage = (void *)((uintptr_t)pvHC & PAGE_BASE_HC_MASK);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cb += (uintptr_t)pvHC & PAGE_OFFSET_MASK;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cb = RT_ALIGN_Z(cb, PAGE_SIZE);
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Add the memory to the hypervisor area.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync RTGCPTR GCPtr;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync PMMLOOKUPHYPER pLookup;
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync int rc = mmR3HyperMap(pVM, cb, pszDesc, &GCPtr, &pLookup);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Lock the heap memory and tell PGM about the locked pages.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync PMMLOCKEDMEM pLockedMem;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync rc = mmr3LockMem(pVM, pvHCPage, cb, fFree ? MM_LOCKED_TYPE_HYPER : MM_LOCKED_TYPE_HYPER_NOFREE, &pLockedMem);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* map the stuff into guest address space. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (pVM->mm.s.fPGMInitialized)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync rc = mmr3MapLocked(pVM, pLockedMem, GCPtr, 0, ~(size_t)0, 0);
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync if (VBOX_SUCCESS(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->enmType = MMLOOKUPHYPERTYPE_LOCKED;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->u.Locked.pvHC = pvHC;
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync pLookup->u.Locked.pLockedMem = pLockedMem;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* done. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync GCPtr |= (uintptr_t)pvHC & PAGE_OFFSET_MASK;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *pGCPtr = GCPtr;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* Don't care about failure clean, we're screwed if this fails anyway. */
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Reserves a hypervisor memory area.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Most frequent usage is fence pages and dynamically mappings like the guest PD and PDPTR.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * @return VBox status code.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM VM handle.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param cb Size of the memory. Will be rounded up to nearest page.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pszDesc Mapping description.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pGCPtr Where to store the assigned GC address. Optional.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncMMR3DECL(int) MMR3HyperReserve(PVM pVM, unsigned cb, const char *pszDesc, PRTGCPTR pGCPtr)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync LogFlow(("MMR3HyperMapHCRam: cb=%d pszDesc=%p:{%s} pGCPtr=%p\n", (int)cb, pszDesc, pszDesc, pGCPtr));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Validate input.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if ( cb <= 0
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync || !pszDesc
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync || !*pszDesc)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync AssertMsgFailed(("Invalid parameter\n"));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VERR_INVALID_PARAMETER;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Add the memory to the hypervisor area.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync RTGCPTR GCPtr;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync PMMLOOKUPHYPER pLookup;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = mmR3HyperMap(pVM, cb, pszDesc, &GCPtr, &pLookup);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->enmType = MMLOOKUPHYPERTYPE_DYNAMIC;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (pGCPtr)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *pGCPtr = GCPtr;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VINF_SUCCESS;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Adds memory to the hypervisor memory arena.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @return VBox status code.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM The VM handle.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param cb Size of the memory. Will be rounded up to neares page.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pszDesc The description of the memory.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pGCPtr Where to store the GC address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param ppLookup Where to store the pointer to the lookup record.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @remark We assume the threading structure of VBox imposes natural
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync * serialization of most functions, this one included.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncstatic int mmR3HyperMap(PVM pVM, const size_t cb, const char *pszDesc, PRTGCPTR pGCPtr, PMMLOOKUPHYPER *ppLookup)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Validate input.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync const uint32_t cbAligned = RT_ALIGN(cb, PAGE_SIZE);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertReturn(cbAligned >= cb, VERR_INVALID_PARAMETER);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (pVM->mm.s.offHyperNextStatic + cbAligned >= pVM->mm.s.cbHyperArea) /* don't use the last page, it's a fence. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("Out of static mapping space in the HMA! offHyperAreaGC=%x cbAligned=%x\n",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVM->mm.s.offHyperNextStatic, cbAligned));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VERR_NO_MEMORY;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Allocate lookup record.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync PMMLOOKUPHYPER pLookup;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = MMHyperAlloc(pVM, sizeof(*pLookup), 1, MM_TAG_MM, (void **)&pLookup);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Initialize it and insert it.
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync */
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync pLookup->offNext = pVM->mm.s.offLookupHyper;
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync pLookup->cb = cbAligned;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->off = pVM->mm.s.offHyperNextStatic;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVM->mm.s.offLookupHyper = (char *)pLookup - (char *)pVM->mm.s.pHyperHeapHC;
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync if (pLookup->offNext != (int32_t)NIL_OFFSET)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->offNext -= pVM->mm.s.offLookupHyper;
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync pLookup->enmType = MMLOOKUPHYPERTYPE_INVALID;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync memset(&pLookup->u, 0xff, sizeof(pLookup->u));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->pszDesc = pszDesc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* Mapping. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *pGCPtr = pVM->mm.s.pvHyperAreaGC + pVM->mm.s.offHyperNextStatic;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVM->mm.s.offHyperNextStatic += cbAligned;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* Return pointer. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *ppLookup = pLookup;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync AssertRC(rc);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync LogFlow(("mmR3HyperMap: returns %Vrc *pGCPtr=%VGv\n", rc, *pGCPtr));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Allocates a new heap.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @returns VBox status code.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM The VM handle.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param cb The size of the new heap.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param ppHeap Where to store the heap pointer on successful return.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncstatic int mmR3HyperHeapCreate(PVM pVM, const size_t cb, PMMHYPERHEAP *ppHeap)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Allocate the hypervisor heap.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync const uint32_t cbAligned = RT_ALIGN_Z(cb, PAGE_SIZE);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertReturn(cbAligned >= cb, VERR_INVALID_PARAMETER);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync void *pv;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = SUPPageAlloc(cbAligned >> PAGE_SHIFT, &pv);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Initialize the heap and first free chunk.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync PMMHYPERHEAP pHeap = (PMMHYPERHEAP)pv;
24b9d11a24f96f5da0351475e0b6486ec4cb0d30vboxsync pHeap->u32Magic = MMHYPERHEAP_MAGIC;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pHeap->pVMHC = pVM;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pHeap->pVMGC = pVM->pVMGC;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pHeap->pbHeapHC = (uint8_t *)pHeap + MMYPERHEAP_HDR_SIZE;
ebd35513cc8c7c67273191d51285629d77a1f736vboxsync //pHeap->pbHeapGC = 0; // set by mmR3HyperHeapMap()
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pHeap->cbHeap = cbAligned - MMYPERHEAP_HDR_SIZE;
ebd35513cc8c7c67273191d51285629d77a1f736vboxsync pHeap->cbFree = pHeap->cbHeap - sizeof(MMHYPERCHUNK);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync //pHeap->offFreeHead = 0;
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync //pHeap->offFreeTail = 0;
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync pHeap->offPageAligned = pHeap->cbHeap;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync //pHeap->HyperHeapStatTree = 0;
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync PMMHYPERCHUNKFREE pFree = (PMMHYPERCHUNKFREE)pHeap->pbHeapHC;
dced478b440a327fb550155c0f73c1ac968ad93bvboxsync pFree->cb = pHeap->cbFree;
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync //pFree->core.offNext = 0;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync MMHYPERCHUNK_SET_TYPE(&pFree->core, MMHYPERCHUNK_FLAGS_FREE);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pFree->core.offHeap = -(int32_t)MMYPERHEAP_HDR_SIZE;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync //pFree->offNext = 0;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync //pFree->offPrev = 0;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync STAMR3Register(pVM, &pHeap->cbHeap, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, "/MM/HyperHeap/cbHeap", STAMUNIT_BYTES, "The heap size.");
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync STAMR3Register(pVM, &pHeap->cbFree, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, "/MM/HyperHeap/cbFree", STAMUNIT_BYTES, "The free space.");
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *ppHeap = pHeap;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VINF_SUCCESS;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("SUPPageAlloc(%d,) -> %Vrc\n", cbAligned >> PAGE_SHIFT, rc));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *ppHeap = NULL;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Allocates a new heap.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncstatic int mmR3HyperHeapMap(PVM pVM, PMMHYPERHEAP pHeap, PRTGCPTR ppHeapGC)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = MMR3HyperMapHCRam(pVM, pHeap, pHeap->cbHeap + MMYPERHEAP_HDR_SIZE, true, "Heap", ppHeapGC);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pHeap->pVMGC = pVM->pVMGC;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pHeap->pbHeapGC = *ppHeapGC + MMYPERHEAP_HDR_SIZE;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* Reserve a page for fencing. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync MMR3HyperReserve(pVM, PAGE_SIZE, "fence", NULL);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#if 0
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Destroys a heap.
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncstatic int mmR3HyperHeapDestroy(PVM pVM, PMMHYPERHEAP pHeap)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* all this is dealt with when unlocking and freeing locked memory. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#endif
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Allocates memory in the Hypervisor (GC VMM) area which never will
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * be freed and doesn't have any offset based relation to other heap blocks.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * The latter means that two blocks allocated by this API will not have the
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * same relative position to each other in GC and HC. In short, never use
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * this API for allocating nodes for an offset based AVL tree!
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * The returned memory is of course zeroed.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync * @returns VBox status code.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM The VM to operate on.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param cb Number of bytes to allocate.
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync * @param uAlignment Required memory alignment in bytes.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Values are 0,8,16,32 and PAGE_SIZE.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * 0 -> default alignment, i.e. 8 bytes.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param enmTag The statistics tag.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param ppv Where to store the address to the allocated
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * memory.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @remark This is assumed not to be used at times when serialization is required.
4f4b2d99ad789c62e8d25156869ee7ea741de8d0vboxsync */
4f4b2d99ad789c62e8d25156869ee7ea741de8d0vboxsyncMMDECL(int) MMR3HyperAllocOnceNoRel(PVM pVM, size_t cb, unsigned uAlignment, MMTAG enmTag, void **ppv)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsg(cb >= 8, ("Hey! Do you really mean to allocate less than 8 bytes?! cb=%d\n", cb));
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync AssertMsg(cb <= _4M, ("Allocating more than 4MB!? (cb=%#x) HMA limit might need adjusting if you allocate more.\n", cb));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Choose between allocating a new chunk of HMA memory
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * and the heap. We will only do BIG allocations from HMA.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if ( cb < _64K
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync && ( uAlignment != PAGE_SIZE
4f4b2d99ad789c62e8d25156869ee7ea741de8d0vboxsync || cb < 48*_1K))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = MMHyperAlloc(pVM, cb, uAlignment, enmTag, ppv);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if ( rc != VERR_MM_HYPER_NO_MEMORY
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync || cb <= 8*_1K)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync Log2(("MMR3HyperAllocOnceNoRel: cb=%#x uAlignment=%#x returns %Rrc and *ppv=%p\n",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cb, uAlignment, rc, *ppv));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Validate alignment.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync switch (uAlignment)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case 0:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case 8:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case 16:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case 32:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case PAGE_SIZE:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync default:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("Invalid alignment %u\n", uAlignment));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VERR_INVALID_PARAMETER;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
48d832e07616531bbb720d9c98103c83b561ebb6vboxsync * Allocate the pages and the HMA space.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cb = RT_ALIGN(cb, PAGE_SIZE);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync void *pvPages;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = SUPPageAlloc(cb >> PAGE_SHIFT, &pvPages);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync RTGCPTR GCPtr;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync rc = MMR3HyperMapHCRam(pVM, pvPages, cb, true, mmR3GetTagName(enmTag), &GCPtr);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *ppv = pvPages;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync Log2(("MMR3HyperAllocOnceNoRel: cb=%#x uAlignment=%#x returns VINF_SUCCESS and *ppv=%p\n",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync cb, uAlignment, *ppv));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync SUPPageFree(pvPages);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (rc == VERR_NO_MEMORY)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync rc = VERR_MM_HYPER_NO_MEMORY;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync Log2(("MMR3HyperAllocOnceNoRel: cb=%#x uAlignment=%#x returns %Rrc\n", cb, uAlignment, rc));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("Failed to allocate %d bytes!\n", cb));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return rc;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Convert hypervisor HC virtual address to HC physical address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @returns HC physical address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM VM Handle
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pvHC Host context physical address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncMMR3DECL(RTHCPHYS) MMR3HyperHCVirt2HCPhys(PVM pVM, void *pvHC)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync PMMLOOKUPHYPER pLookup = (PMMLOOKUPHYPER)((char*)pVM->mm.s.pHyperHeapHC + pVM->mm.s.offLookupHyper);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync for (;;)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync switch (pLookup->enmType)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case MMLOOKUPHYPERTYPE_LOCKED:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync unsigned off = (char *)pvHC - (char *)pLookup->u.Locked.pvHC;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (off < pLookup->cb)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return (pLookup->u.Locked.pLockedMem->aPhysPages[off >> PAGE_SHIFT].Phys & X86_PTE_PAE_PG_MASK) | (off & PAGE_OFFSET_MASK);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case MMLOOKUPHYPERTYPE_HCPHYS:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync unsigned off = (char *)pvHC - (char *)pLookup->u.HCPhys.pvHC;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (off < pLookup->cb)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return pLookup->u.HCPhys.HCPhys + off;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case MMLOOKUPHYPERTYPE_GCPHYS:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case MMLOOKUPHYPERTYPE_DYNAMIC:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* can convert these kind of records. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync default:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("enmType=%d\n", pLookup->enmType));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* next */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if ((unsigned)pLookup->offNext == NIL_OFFSET)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup = (PMMLOOKUPHYPER)((char *)pLookup + pLookup->offNext);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("pvHC=%p is not inside the hypervisor memory area!\n", pvHC));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return NIL_RTHCPHYS;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#if 0 /* unused, not implemented */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Convert hypervisor HC physical address to HC virtual address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @returns HC virtual address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM VM Handle
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param HCPhys Host context physical address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncMMR3DECL(void *) MMR3HyperHCPhys2HCVirt(PVM pVM, RTHCPHYS HCPhys)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync void *pv;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync int rc = MMR3HyperHCPhys2HCVirtEx(pVM, HCPhys, &pv);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if (VBOX_SUCCESS(rc))
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return pv;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync AssertMsgFailed(("Invalid address HCPhys=%x rc=%d\n", HCPhys, rc));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return NULL;
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Convert hypervisor HC physical address to HC virtual address.
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @returns VBox status.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM VM Handle
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param HCPhys Host context physical address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param ppv Where to store the HC virtual address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncMMR3DECL(int) MMR3HyperHCPhys2HCVirtEx(PVM pVM, RTHCPHYS HCPhys, void **ppv)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /*
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Linear search.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /** @todo implement when actually used. */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VERR_INVALID_POINTER;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync#endif /* unused, not implemented */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Read hypervisor memory from GC virtual address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync * @returns VBox status.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM VM handle.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pvDst Destination address (HC of course).
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync * @param GCPtr GC virtual address.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param cb Number of bytes to read.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncMMR3DECL(int) MMR3HyperReadGCVirt(PVM pVM, void *pvDst, RTGCPTR GCPtr, size_t cb)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync{
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync if (GCPtr - pVM->mm.s.pvHyperAreaGC >= pVM->mm.s.cbHyperArea)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return VERR_INVALID_PARAMETER;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync return PGMR3MapRead(pVM, pvDst, GCPtr, cb);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync/**
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * Info handler for 'hma', it dumps the list of lookup records for the hypervisor memory area.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync *
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pVM The VM handle.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pHlp Callback functions for doing output.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync * @param pszArgs Argument string. Optional and specific to the handler.
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsyncstatic DECLCALLBACK(void) mmR3HyperInfoHma(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
d09ef734532edd0e40ffe9a471e0a31152572065vboxsync{
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync pHlp->pfnPrintf(pHlp, "Hypervisor Memory Area (HMA) Layout: Base %VGv, 0x%08x bytes\n",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pVM->mm.s.pvHyperAreaGC, pVM->mm.s.cbHyperArea);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync PMMLOOKUPHYPER pLookup = (PMMLOOKUPHYPER)((char*)pVM->mm.s.pHyperHeapHC + pVM->mm.s.offLookupHyper);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync for (;;)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync switch (pLookup->enmType)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync {
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case MMLOOKUPHYPERTYPE_LOCKED:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pHlp->pfnPrintf(pHlp, "%VGv-%VGv %VHv LOCKED %-*s %s\n",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->off + pVM->mm.s.pvHyperAreaGC,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->off + pVM->mm.s.pvHyperAreaGC + pLookup->cb,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->u.Locked.pvHC,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync sizeof(RTHCPTR) * 2,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->u.Locked.pLockedMem->eType == MM_LOCKED_TYPE_HYPER_NOFREE
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync ? "nofree" : "autofree",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->pszDesc);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case MMLOOKUPHYPERTYPE_HCPHYS:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pHlp->pfnPrintf(pHlp, "%VGv-%VGv %VHv HCPHYS %VHp %s\n",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->off + pVM->mm.s.pvHyperAreaGC,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->off + pVM->mm.s.pvHyperAreaGC + pLookup->cb,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->u.HCPhys.pvHC, pLookup->u.HCPhys.HCPhys,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->pszDesc);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case MMLOOKUPHYPERTYPE_GCPHYS:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pHlp->pfnPrintf(pHlp, "%VGv-%VGv %*s GCPHYS %VGp%*s %s\n",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->off + pVM->mm.s.pvHyperAreaGC,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->off + pVM->mm.s.pvHyperAreaGC + pLookup->cb,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync sizeof(RTHCPTR) * 2, "",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->u.GCPhys.GCPhys, RT_ABS(sizeof(RTHCPHYS) - sizeof(RTGCPHYS)) * 2, "",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->pszDesc);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync case MMLOOKUPHYPERTYPE_DYNAMIC:
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pHlp->pfnPrintf(pHlp, "%VGv-%VGv %*s DYNAMIC %*s %s\n",
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync pLookup->off + pVM->mm.s.pvHyperAreaGC,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->off + pVM->mm.s.pvHyperAreaGC + pLookup->cb,
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync sizeof(RTHCPTR) * 2, "",
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync sizeof(RTHCPTR) * 2, "",
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup->pszDesc);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync default:
810e2dff19cb2bda7ee6f98fa1a9e25ca1bb32d8vboxsync AssertMsgFailed(("enmType=%d\n", pLookup->enmType));
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync /* next */
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync if ((unsigned)pLookup->offNext == NIL_OFFSET)
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync break;
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync pLookup = (PMMLOOKUPHYPER)((char *)pLookup + pLookup->offNext);
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync }
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync}
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync
3c3a5ab35783f4d31cb5d3a15db9daadeb804daavboxsync