genode/repos/ports/src/virtualbox5/mm.cc
Norman Feske bf92232698 libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.

The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.

The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.

There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.

Issue #3497
2019-11-19 14:10:55 +01:00

345 lines
7.7 KiB
C++

/*
* \brief VirtualBox memory manager (MMR3)
* \author Norman Feske
* \date 2013-08-20
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* Genode includes */
#include <base/log.h>
#include <util/string.h>
#include <rm_session/connection.h>
#include <base/attached_ram_dataspace.h>
/* VirtualBox includes */
#include <VBox/vmm/mm.h>
#include <VBox/vmm/cfgm.h>
#include <VBox/err.h>
#include <VBox/vmm/gmm.h>
#include "MMInternal.h"
#include <VBox/vmm/vm.h>
#include <VBox/vmm/pgm.h>
#include <iprt/err.h>
#include <iprt/mem.h>
#include <iprt/string.h>
/* libc memory allocator */
#include <internal/mem_alloc.h>
#include "util.h"
#include "mm.h"
#include "vmm.h"
enum { VERBOSE_MM = false };
static struct {
Sub_rm_connection * conn;
Libc::Mem_alloc_impl * heap;
} memory_regions [MM_TAG_HM + 1];
static Libc::Mem_alloc * heap_by_mmtag(MMTAG enmTag)
{
enum { REGION_SIZE = 4096 * 4096 };
static Genode::Lock memory_init_lock;
Assert(enmTag < sizeof(memory_regions) / sizeof(memory_regions[0]));
if (memory_regions[enmTag].conn)
return memory_regions[enmTag].heap;
Genode::Lock::Guard guard(memory_init_lock);
if (memory_regions[enmTag].conn)
return memory_regions[enmTag].heap;
memory_regions[enmTag].conn = new Sub_rm_connection(genode_env(), REGION_SIZE);
memory_regions[enmTag].heap = new Libc::Mem_alloc_impl(*memory_regions[enmTag].conn,
genode_env().ram());
return memory_regions[enmTag].heap;
}
static Libc::Mem_alloc * heap_by_pointer(void * pv)
{
for (unsigned i = 0; i < sizeof(memory_regions) / sizeof(memory_regions[0]); i++) {
if (!memory_regions[i].heap)
continue;
if (memory_regions[i].conn->contains(pv))
return memory_regions[i].heap;
}
return nullptr;
}
int MMR3Init(PVM) { return VINF_SUCCESS; }
int MMR3Term(PVM) { return VINF_SUCCESS; }
int MMR3InitUVM(PUVM) { return VINF_SUCCESS; }
void MMR3TermUVM(PUVM) { }
void *MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize)
{
return heap_by_mmtag(enmTag)->alloc(cbSize, Genode::log2(RTMEM_ALIGNMENT));
}
/**
* Return alignment to be used for allocations of given tag
*/
static unsigned align_by_mmtag(MMTAG enmTag)
{
switch (enmTag) {
case MM_TAG_PGM:
case MM_TAG_PDM_DEVICE:
case MM_TAG_PDM_DEVICE_USER:
case MM_TAG_VMM:
case MM_TAG_CPUM_CTX:
return 12;
case MM_TAG_CPUM_CPUID:
case MM_TAG_CPUM_MSRS:
return Genode::log2(32);
case MM_TAG_PGM_PHYS:
return Genode::log2(16);
default:
return Genode::log2(RTMEM_ALIGNMENT);
}
}
/**
* Round allocation size for a given tag
*/
static size_t round_size_by_mmtag(MMTAG enmTag, size_t cb)
{
return Genode::align_addr(cb, align_by_mmtag(enmTag));
}
void *MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize)
{
size_t const rounded_size = round_size_by_mmtag(enmTag, cbSize);
return heap_by_mmtag(enmTag)->alloc(rounded_size, align_by_mmtag(enmTag));
}
void *MMR3HeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize)
{
void * const ret = MMR3HeapAlloc(pVM, enmTag, cbSize);
if (ret)
Genode::memset(ret, 0, cbSize);
return ret;
}
void * MMR3HeapAllocZU(PUVM pUVM, MMTAG enmTag, size_t cbSize) {
void * const ret = MMR3HeapAllocU(pUVM, enmTag, cbSize);
if (ret)
Genode::memset(ret, 0, cbSize);
return ret;
}
void * MMR3UkHeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize, PRTR0PTR pR0Ptr)
{
if (pR0Ptr)
*pR0Ptr = NIL_RTR0PTR;
return MMR3HeapAllocZ(pVM, enmTag, cbSize);
}
int MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
{
*ppv = MMR3HeapAllocZ(pVM, enmTag, cbSize);
return VINF_SUCCESS;
}
int MMR3HyperInitFinalize(PVM)
{
return VINF_SUCCESS;
}
int MMR3HyperSetGuard(PVM, void* ptr, size_t, bool)
{
return VINF_SUCCESS;
}
int MMR3HyperAllocOnceNoRel(PVM pVM, size_t cb, unsigned uAlignment,
MMTAG enmTag, void **ppv)
{
AssertRelease(align_by_mmtag(enmTag) >= (uAlignment ? Genode::log2(uAlignment) : 0));
unsigned const align_log2 = uAlignment ? Genode::log2(uAlignment)
: align_by_mmtag(enmTag);
size_t const rounded_size = round_size_by_mmtag(enmTag, cb);
void *ret = heap_by_mmtag(enmTag)->alloc(rounded_size, align_log2);
if (ret)
Genode::memset(ret, 0, cb);
*ppv = ret;
return VINF_SUCCESS;
}
int MMR3HyperAllocOnceNoRelEx(PVM pVM, size_t cb, uint32_t uAlignment,
MMTAG enmTag, uint32_t fFlags, void **ppv)
{
AssertRelease(align_by_mmtag(enmTag) >= (uAlignment ? Genode::log2(uAlignment) : 0));
return MMR3HyperAllocOnceNoRel(pVM, cb, uAlignment, enmTag, ppv);
}
int MMHyperAlloc(PVM pVM, size_t cb, unsigned uAlignment, MMTAG enmTag, void **ppv)
{
if (!(align_by_mmtag(enmTag) >= (uAlignment ? Genode::log2(uAlignment) : 0)))
Genode::error(__func__, " ", (int)enmTag, " ", uAlignment, " ", (int)MM_TAG_PGM);
AssertRelease(align_by_mmtag(enmTag) >= (uAlignment ? Genode::log2(uAlignment) : 0));
*ppv = MMR3HeapAllocZ(pVM, enmTag, cb);
return VINF_SUCCESS;
}
int MMHyperFree(PVM pVM, void *pv)
{
MMR3HeapFree(pv);
return VINF_SUCCESS;
}
int MMHyperDupMem(PVM pVM, const void *pvSrc, size_t cb,
unsigned uAlignment, MMTAG enmTag, void **ppv)
{
int rc = MMHyperAlloc(pVM, cb, uAlignment, enmTag, ppv);
if (RT_SUCCESS(rc))
memcpy(*ppv, pvSrc, cb);
return rc;
}
bool MMHyperIsInsideArea(PVM, RTGCPTR ptr)
{
Genode::log(__func__, " called");
return false;
}
void MMR3HeapFree(void *pv)
{
Libc::Mem_alloc *heap = heap_by_pointer(pv);
Assert(heap);
heap->free(pv);
}
int MMR3HyperMapHCPhys(PVM pVM, void *pvR3, RTR0PTR pvR0, RTHCPHYS HCPhys,
size_t cb, const char *pszDesc, PRTGCPTR pGCPtr)
{
static_assert(sizeof(*pGCPtr) == sizeof(HCPhys) , "pointer transformation bug");
*pGCPtr = (RTGCPTR)HCPhys;
return VINF_SUCCESS;
}
int MMR3HyperReserve(PVM pVM, unsigned cb, const char *pszDesc, PRTGCPTR pGCPtr)
{
if (VERBOSE_MM)
Genode::log("MMR3HyperReserve: cb=", Genode::Hex(cb), ", "
"pszDesc=", pszDesc);
return VINF_SUCCESS;
}
int MMR3AdjustFixedReservation(PVM, int32_t, const char *pszDesc)
{
if (VERBOSE_MM)
Genode::log(__func__, " called for '", pszDesc, "'");
return VINF_SUCCESS;
}
int MMR3HyperMapMMIO2(PVM pVM, PPDMDEVINS pDevIns, uint32_t iSubDev,
uint32_t iRegion,
RTGCPHYS off, RTGCPHYS cb, const char *pszDesc,
PRTRCPTR pRCPtr)
{
if (VERBOSE_MM)
Genode::log("pszDesc=", pszDesc, " iRegion=", iRegion, " "
"off=", Genode::Hex(off), " cb=", Genode::Hex(cb));
return VINF_SUCCESS;
}
VMMR3DECL(RTHCPHYS) MMR3HyperHCVirt2HCPhys(PVM pVM, void *pvR3) {
return (RTHCPHYS)(uintptr_t)pvR3; }
VMMDECL(RTHCPHYS) MMPage2Phys(PVM pVM, void *pvPage) {
return (RTHCPHYS)(uintptr_t)pvPage; }
VMMR3DECL(void *) MMR3PageAlloc(PVM pVM)
{
using Genode::Attached_ram_dataspace;
Attached_ram_dataspace * ds = new Attached_ram_dataspace(genode_env().ram(),
genode_env().rm(),
4096);
return ds->local_addr<void>();
}
VMMR3DECL(void *) MMR3PageAllocLow(PVM pVM) { return MMR3PageAlloc(pVM); }
int MMR3ReserveHandyPages(PVM pVM, uint32_t cHandyPages)
{
if (VERBOSE_MM)
Genode::log(__func__, " called");
return VINF_SUCCESS;
}
VMMDECL(void *) MMHyperHeapOffsetToPtr(PVM pVM, uint32_t offHeap)
{
if (sizeof(void*) == 8) {
uint64_t ptr = offHeap;
return reinterpret_cast<void *>(ptr);
}
return reinterpret_cast<void *>(offHeap);
}
VMMDECL(uint32_t) MMHyperHeapPtrToOffset(PVM pVM, void *pv)
{
Genode::addr_t offset = reinterpret_cast<Genode::addr_t>(pv);
Assert (reinterpret_cast<void *>(offset) == pv);
return offset;
}