sel4: handle platform_pd destruction

Issue #2044
This commit is contained in:
Alexander Boettcher 2016-07-13 16:03:21 +02:00 committed by Christian Helmuth
parent ad7748592a
commit b0c3427ed4
5 changed files with 93 additions and 11 deletions

View File

@ -109,6 +109,10 @@ class Genode::Cnode_base
class Genode::Cnode : public Cnode_base, Noncopyable class Genode::Cnode : public Cnode_base, Noncopyable
{ {
private:
addr_t _phys = 0UL;
public: public:
class Untyped_lookup_failed : Exception { }; class Untyped_lookup_failed : Exception { };
@ -135,7 +139,7 @@ class Genode::Cnode : public Cnode_base, Noncopyable
: :
Cnode_base(dst_idx, size_log2) Cnode_base(dst_idx, size_log2)
{ {
create<Cnode_kobj>(phys_alloc, parent_sel, dst_idx, size_log2); _phys = create<Cnode_kobj>(phys_alloc, parent_sel, dst_idx, size_log2);
} }
/** /**
@ -160,13 +164,35 @@ class Genode::Cnode : public Cnode_base, Noncopyable
create<Cnode_kobj>(untyped_pool, parent_sel, dst_idx, size_log2); create<Cnode_kobj>(untyped_pool, parent_sel, dst_idx, size_log2);
} }
~Cnode() void destruct(Range_allocator &phys_alloc)
{ {
/* convert CNode back to untyped memory */
/* revert phys allocation */ /* revert phys allocation */
PDBG("not implemented"); if (!_phys) {
error("invalid call to destruct Cnode");
return;
}
int ret = seL4_CNode_Delete(seL4_CapInitThreadCNode,
sel().value(), 32);
if (ret != seL4_NoError)
error(__PRETTY_FUNCTION__, ": seL4_CNode_Delete (",
Hex(sel().value()), ") returned ", ret);
Untyped_memory::free_page(phys_alloc, _phys);
_phys = ~0UL;
}
~Cnode()
{
if (_phys == ~0UL)
return;
/* convert CNode back to untyped memory */
error(__FUNCTION__, " - not implemented phys=", Hex(_phys),
" sel=", Hex(sel().value()));
} }
}; };

View File

@ -79,6 +79,8 @@ class Genode::Page_table_registry
Page_table(addr_t addr) : addr(addr) { } Page_table(addr_t addr) : addr(addr) { }
Entry *first() { return _entries.first(); }
Entry &lookup(addr_t addr) Entry &lookup(addr_t addr)
{ {
for (Entry *e = _entries.first(); e; e = e->next()) { for (Entry *e = _entries.first(); e; e = e->next()) {
@ -221,6 +223,12 @@ class Genode::Page_table_registry
*/ */
Page_table_registry(Allocator &md_alloc) { } Page_table_registry(Allocator &md_alloc) { }
~Page_table_registry()
{
if (_page_tables.first())
error("still entries in page table registry in destruction");
}
/** /**
* Register page table * Register page table
* *
@ -299,6 +307,22 @@ class Genode::Page_table_registry
PDBG("no PT entry found for virtual address 0x%lx", addr); PDBG("no PT entry found for virtual address 0x%lx", addr);
} }
} }
template <typename FN>
void apply_to_and_destruct_all(FN const &fn)
{
for (Page_table *pt; (pt = _page_tables.first());) {
Page_table::Entry *entry = pt->first();
for (; entry; entry = entry->next())
fn(entry->sel);
pt->flush_all(_page_table_entry_alloc);
_page_tables.remove(pt);
destroy(_page_table_alloc, pt);
}
}
}; };
#endif /* _CORE__INCLUDE__PAGE_TABLE_REGISTRY_H_ */ #endif /* _CORE__INCLUDE__PAGE_TABLE_REGISTRY_H_ */

View File

@ -53,6 +53,12 @@ struct Genode::Untyped_memory
} }
static inline void free_page(Range_allocator &phys_alloc, Genode::addr_t addr)
{
phys_alloc.free(reinterpret_cast<void *>(addr));
}
/** /**
* Local utility solely used by 'untyped_sel' and 'frame_sel' * Local utility solely used by 'untyped_sel' and 'frame_sel'
*/ */

View File

@ -113,8 +113,10 @@ class Genode::Vm_space
LEAF_CNODE_SIZE_LOG2, phys_alloc); LEAF_CNODE_SIZE_LOG2, phys_alloc);
} }
void destruct(Cap_sel_alloc &cap_sel_alloc) void destruct(Cap_sel_alloc &cap_sel_alloc,
Range_allocator &phys_alloc)
{ {
_cnode->destruct(phys_alloc);
cap_sel_alloc.free(_cnode->sel()); cap_sel_alloc.free(_cnode->sel());
} }
@ -306,16 +308,31 @@ class Genode::Vm_space
_vm_pad_cnode.copy(cspace, _vm_3rd_cnode.sel(), Cnode_index(0)); _vm_pad_cnode.copy(cspace, _vm_3rd_cnode.sel(), Cnode_index(0));
/* insert 2nd-level VM-pad CNode into 1st-level CNode */ /* insert 2nd-level VM-pad CNode into 1st-level CNode */
_top_level_cnode.copy(cspace, _vm_pad_cnode.sel(), Cnode_index(id)); _top_level_cnode.copy(cspace, _vm_pad_cnode.sel(), Cnode_index(_id));
} }
~Vm_space() ~Vm_space()
{ {
_cap_sel_alloc.free(_vm_pad_cnode.sel()); /* delete copy of the mapping's page-frame selectors */
_cap_sel_alloc.free(_vm_3rd_cnode.sel()); _page_table_registry.apply_to_and_destruct_all([&] (unsigned idx) {
_leaf_cnode(idx).remove(_leaf_cnode_entry(idx));
_sel_alloc.free(idx);
});
for (unsigned i = 0; i < NUM_LEAF_CNODES; i++) {
_vm_3rd_cnode.remove(Cnode_index(i));
_vm_cnodes[i].destruct(_cap_sel_alloc, _phys_alloc);
}
_vm_pad_cnode.remove(Cnode_index(0));
_top_level_cnode.remove(Cnode_index(_id));
_vm_3rd_cnode.destruct(_phys_alloc);
_vm_pad_cnode.destruct(_phys_alloc);
_cap_sel_alloc.free(_vm_3rd_cnode.sel());
_cap_sel_alloc.free(_vm_pad_cnode.sel());
for (unsigned i = 0; i < NUM_LEAF_CNODES; i++)
_vm_cnodes[i].destruct(_cap_sel_alloc);
} }
void map(addr_t from_phys, addr_t to_virt, size_t num_pages, void map(addr_t from_phys, addr_t to_virt, size_t num_pages,

View File

@ -194,6 +194,15 @@ Platform_pd::Platform_pd(Allocator * md_alloc, char const *label,
Platform_pd::~Platform_pd() Platform_pd::~Platform_pd()
{ {
for (unsigned i = 0; i < sizeof(_cspace_cnode_2nd) /
sizeof(_cspace_cnode_2nd[0]); i++) {
_cspace_cnode_2nd[i]->destruct(*platform()->ram_alloc());
platform_specific()->core_sel_alloc().free(_cspace_cnode_2nd[i]->sel());
}
_cspace_cnode_1st.destruct(*platform()->ram_alloc());
platform_specific()->core_sel_alloc().free(_cspace_cnode_1st.sel());
/* invalidate weak pointers to this object */ /* invalidate weak pointers to this object */
Address_space::lock_for_destruction(); Address_space::lock_for_destruction();
} }