From 8366d070822c49f94f693e84caa8b77388177c0d Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Thu, 24 Apr 2014 16:21:07 +0200 Subject: [PATCH] vbox: use separate memory spaces Use the libc Mem_alloc implementation per MMTYP of virtualbox. With this the invariant that all memory allocation of a MMTYP are dense located. Fixes #1130 --- libports/src/lib/libc/libc_mem_alloc.h | 5 +- ports/src/virtualbox/mm.cc | 118 +++++++++++++++++++++---- 2 files changed, 106 insertions(+), 17 deletions(-) diff --git a/libports/src/lib/libc/libc_mem_alloc.h b/libports/src/lib/libc/libc_mem_alloc.h index 5e608e393..5e9ad5480 100644 --- a/libports/src/lib/libc/libc_mem_alloc.h +++ b/libports/src/lib/libc/libc_mem_alloc.h @@ -108,9 +108,10 @@ namespace Libc { public: - Mem_alloc_impl() + Mem_alloc_impl(Genode::Rm_session * rm = Genode::env()->rm_session(), + Genode::Ram_session * ram = Genode::env()->ram_session()) : - _ds_pool(Genode::env()->ram_session(), Genode::env()->rm_session()), + _ds_pool(ram, rm), _alloc(0), _chunk_size(MIN_CHUNK_SIZE) { } diff --git a/ports/src/virtualbox/mm.cc b/ports/src/virtualbox/mm.cc index 5c9ab123d..7ab554be9 100644 --- a/ports/src/virtualbox/mm.cc +++ b/ports/src/virtualbox/mm.cc @@ -14,6 +14,7 @@ /* Genode includes */ #include #include +#include /* VirtualBox includes */ #include @@ -32,6 +33,96 @@ #include "util.h" +/** + * Sub rm_session as backend for the Libc::Mem_alloc implementation. + * Purpose is that memory allocation by vbox of a specific type (MMTYP) are + * all located within a 2G virtual window. Reason is that virtualbox converts + * internally pointers at several places in base + offset, whereby offset is + * a int32_t type. + */ +class Sub_rm_connection : public Genode::Rm_connection +{ + + private: + + Genode::addr_t const _offset; + Genode::size_t const _size; + + public: + + Sub_rm_connection(Genode::size_t size) + : + Genode::Rm_connection(0, size), + _offset(Genode::env()->rm_session()->attach(dataspace())), + _size(size) + { } + + Local_addr attach(Genode::Dataspace_capability ds, + Genode::size_t size = 0, Genode::off_t offset = 0, + bool use_local_addr = false, + Local_addr local_addr = (void *)0, + bool executable = false) + { + Local_addr addr = Rm_connection::attach(ds, size, offset, + use_local_addr, local_addr, + executable); + Genode::addr_t new_addr = addr; + new_addr += _offset; + return Local_addr(new_addr); + } + + bool contains(void * ptr) + { + Genode::addr_t addr = reinterpret_cast(ptr); + + return (_offset <= addr && addr < _offset + _size); + } + +}; + + +static struct { + Sub_rm_connection * conn; + Libc::Mem_alloc_impl * heap; +} memory_regions [MM_TAG_HWACCM]; + + +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(REGION_SIZE); + memory_regions[enmTag].heap = new Libc::Mem_alloc_impl(memory_regions[enmTag].conn); + + 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 pVM) { PDBG("MMR3Init called, not implemented"); @@ -48,7 +139,7 @@ int MMR3InitUVM(PUVM pUVM) void *MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize) { - return Libc::mem_alloc()->alloc(cbSize, Genode::log2(RTMEM_ALIGNMENT)); + return heap_by_mmtag(enmTag)->alloc(cbSize, Genode::log2(RTMEM_ALIGNMENT)); } @@ -79,13 +170,7 @@ static size_t round_size_by_mmtag(MMTAG enmTag, size_t cb) void *MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize) { size_t const rounded_size = round_size_by_mmtag(enmTag, cbSize); - - void *ret = Libc::mem_alloc()->alloc(rounded_size, align_by_mmtag(enmTag)); - -// PINF("MMR3HeapAlloc: enmTag=%d cbSize=0x%zx -> 0x%p (0x%zx)", -// enmTag, cbSize, ret, rounded_size); - - return ret; + return heap_by_mmtag(enmTag)->alloc(rounded_size, align_by_mmtag(enmTag)); } @@ -116,13 +201,10 @@ int MMR3HyperAllocOnceNoRel(PVM pVM, size_t cb, unsigned uAlignment, size_t const rounded_size = round_size_by_mmtag(enmTag, cb); - void *ret = Libc::mem_alloc()->alloc(rounded_size, align_log2); + void *ret = heap_by_mmtag(enmTag)->alloc(rounded_size, align_log2); if (ret) Genode::memset(ret, 0, cb); - PINF("MMR3HyperAllocOnceNoRel: enmTag=%d align_log2=%u cb=0x%zx -> 0x%p", - enmTag, align_log2, cb, ret); - *ppv = ret; return VINF_SUCCESS; @@ -147,13 +229,19 @@ int MMHyperAlloc(PVM pVM, size_t cb, unsigned uAlignment, MMTAG enmTag, void **p int MMHyperFree(PVM pVM, void *pv) { - Libc::mem_alloc()->free(pv); - + MMR3HeapFree(pv); return VINF_SUCCESS; } -void MMR3HeapFree(void *pv) { Libc::mem_alloc()->free(pv); } +void MMR3HeapFree(void *pv) +{ + Libc::Mem_alloc *heap = heap_by_pointer(pv); + + Assert(heap); + + heap->free(pv); +} RTR0PTR MMHyperR3ToR0(PVM pVM, RTR3PTR R3Ptr) { return (RTR0PTR)R3Ptr; }