vm_session: track dataspaces used by attach

Track the dataspaces used by attach and add handling of flushing VM space
when dataspace gets destroyed (not triggered via the vm_session interface).

Issue #3111
This commit is contained in:
Alexander Boettcher
2019-04-02 17:41:30 +02:00
committed by Christian Helmuth
parent 169c51d50d
commit 450c8dc149
23 changed files with 556 additions and 216 deletions

View File

@ -53,18 +53,12 @@ void Vm_session_component::_attach(addr_t phys_addr, addr_t vm_addr, size_t size
}
void Vm_session_component::attach(Dataspace_capability ds_cap, addr_t vm_addr)
void Vm_session_component::_attach_vm_memory(Dataspace_component &dsc,
addr_t const vm_addr,
bool const /* executable */,
bool const /* writeable */)
{
/* check dataspace validity */
_ds_ep->apply(ds_cap, [&] (Dataspace_component *dsc) {
if (!dsc) throw Invalid_dataspace();
/* unsupported - deny otherwise arbitrary physical memory can be mapped to a VM */
if (dsc->managed())
throw Invalid_dataspace();
_attach(dsc->phys_addr(), vm_addr, dsc->size());
});
_attach(dsc.phys_addr(), vm_addr, dsc.size());
}
@ -75,9 +69,10 @@ void Vm_session_component::attach_pic(addr_t vm_addr)
}
void Vm_session_component::detach(addr_t vm_addr, size_t size) {
_table.remove_translation(vm_addr, size, _table_array.alloc()); }
void Vm_session_component::_detach_vm_memory(addr_t vm_addr, size_t size)
{
_table.remove_translation(vm_addr, size, _table_array.alloc());
}
void * Vm_session_component::_alloc_table()
@ -102,8 +97,9 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ds_ep,
:
Ram_quota_guard(resources.ram_quota),
Cap_quota_guard(resources.cap_quota),
_ds_ep(&ds_ep),
_ep(ds_ep),
_constrained_md_ram_alloc(ram_alloc, _ram_quota_guard(), _cap_quota_guard()),
_sliced_heap(_constrained_md_ram_alloc, region_map),
_region_map(region_map),
_table(*construct_at<Table>(_alloc_table())),
_table_array(*(new (cma()) Array([this] (void * virt) {
@ -117,11 +113,25 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint &ds_ep,
_constrained_md_ram_alloc.free(_ds_cap);
throw;
}
/* configure managed VM area */
_map.add_range(0, 0UL - 0x1000);
_map.add_range(0UL - 0x1000, 0x1000);
}
Vm_session_component::~Vm_session_component()
{
/* detach all regions */
while (true) {
addr_t out_addr = 0;
if (!_map.any_block_addr(&out_addr))
break;
detach(out_addr);
}
/* free region in allocator */
if (_ds_cap.valid()) {
_region_map.detach(_ds_addr);

View File

@ -16,6 +16,7 @@
/* Genode includes */
#include <base/allocator.h>
#include <base/allocator_avl.h>
#include <base/session_object.h>
#include <vm_session/vm_session.h>
#include <dataspace/capability.h>
@ -23,6 +24,7 @@
/* Core includes */
#include <object.h>
#include <region_map_component.h>
#include <translation_table.h>
#include <kernel/vm.h>
@ -35,10 +37,13 @@ class Genode::Vm_session_component
private Ram_quota_guard,
private Cap_quota_guard,
public Rpc_object<Vm_session, Vm_session_component>,
public Region_map_detach,
private Kernel_object<Kernel::Vm>
{
private:
typedef Allocator_avl_tpl<Rm_region> Avl_region;
/*
* Noncopyable
*/
@ -48,8 +53,10 @@ class Genode::Vm_session_component
using Table = Hw::Level_1_stage_2_translation_table;
using Array = Table::Allocator::Array<Kernel::DEFAULT_TRANSLATION_TABLE_MAX>;
Rpc_entrypoint *_ds_ep;
Rpc_entrypoint &_ep;
Constrained_ram_allocator _constrained_md_ram_alloc;
Sliced_heap _sliced_heap;
Avl_region _map { &_sliced_heap };
Region_map &_region_map;
Ram_dataspace_capability _ds_cap { };
Region_map::Local_addr _ds_addr { 0 };
@ -64,6 +71,9 @@ class Genode::Vm_session_component
void * _alloc_table();
void _attach(addr_t phys_addr, addr_t vm_addr, size_t size);
void _attach_vm_memory(Dataspace_component &, addr_t, bool, bool);
void _detach_vm_memory(addr_t, size_t);
protected:
Ram_quota_guard &_ram_quota_guard() { return *this; }
@ -79,6 +89,12 @@ class Genode::Vm_session_component
Diag, Ram_allocator &ram, Region_map &);
~Vm_session_component();
/*********************************
** Region_map_detach interface **
*********************************/
void detach(Region_map::Local_addr) override;
void unmap_region(addr_t, size_t) override;
/**************************
** Vm session interface **