sel4: flush page table allocator if full

Issue #2044
This commit is contained in:
Alexander Boettcher 2016-07-08 13:44:52 +02:00 committed by Christian Helmuth
parent 90390fe053
commit 998dfa6c5e
4 changed files with 54 additions and 10 deletions

View File

@ -35,7 +35,13 @@ namespace Genode {
*/
inline bool map_local(addr_t from_phys, addr_t to_virt, size_t num_pages)
{
platform_specific()->core_vm_space().map(from_phys, to_virt, num_pages);
enum { DONT_FLUSH = false };
try {
platform_specific()->core_vm_space().map(from_phys, to_virt,
num_pages, DONT_FLUSH);
} catch (Page_table_registry::Mapping_cache_full) {
return false;
}
return true;
}

View File

@ -17,6 +17,7 @@
/* Genode includes */
#include <util/list.h>
#include <base/exception.h>
#include <base/log.h>
/* core includes */
#include <util.h>
@ -30,6 +31,7 @@ class Genode::Page_table_registry
public:
class Lookup_failed : Exception { };
class Mapping_cache_full : Exception { };
private:
@ -93,7 +95,11 @@ class Genode::Page_table_registry
return;
}
_entries.insert(new (entry_alloc) Entry(addr, sel));
try {
_entries.insert(new (entry_alloc) Entry(addr, sel));
} catch (Genode::Allocator::Out_of_memory) {
throw Mapping_cache_full();
}
}
void remove_entry(Allocator &entry_alloc, addr_t addr)
@ -107,6 +113,14 @@ class Genode::Page_table_registry
PWRN("trying to remove non-existing page frame for 0x%lx", addr);
}
}
void flush_all(Allocator &entry_alloc)
{
for (; Entry *entry = _entries.first();) {
_entries.remove(entry);
destroy(entry_alloc, entry);
}
}
};
/**
@ -257,6 +271,13 @@ class Genode::Page_table_registry
}
}
void flush_cache()
{
for (Page_table *pt = _page_tables.first(); pt; pt = pt->next())
pt->flush_all(_page_table_entry_alloc);
}
/**
* Apply functor 'fn' to selector of specified virtual address
*

View File

@ -148,7 +148,7 @@ class Genode::Vm_space
*/
unsigned _idx_to_sel(unsigned idx) const { return (_id << 20) | idx; }
void _map_page(addr_t from_phys, addr_t to_virt)
void _map_page(addr_t from_phys, addr_t to_virt, bool flush_support)
{
/* allocate page-table entry selector */
unsigned pte_idx = _sel_alloc.alloc();
@ -164,7 +164,19 @@ class Genode::Vm_space
Cnode_index(_leaf_cnode_entry(pte_idx)));
/* remember relationship between pte_sel and the virtual address */
_page_table_registry.insert_page_table_entry(to_virt, pte_idx);
try {
_page_table_registry.insert_page_table_entry(to_virt, pte_idx);
} catch (Page_table_registry::Mapping_cache_full) {
if (!flush_support)
throw;
warning("flush page table entries - mapping cache full");
_page_table_registry.flush_cache();
/* re-try once */
_page_table_registry.insert_page_table_entry(to_virt, pte_idx);
}
/*
* Insert copy of page-frame selector into page table
@ -300,7 +312,8 @@ class Genode::Vm_space
_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,
bool flush_support = true)
{
Lock::Guard guard(_lock);
@ -310,7 +323,7 @@ class Genode::Vm_space
for (size_t i = 0; i < num_pages; i++) {
off_t const offset = i << get_page_size_log2();
_map_page(from_phys + offset, to_virt + offset);
_map_page(from_phys + offset, to_virt + offset, flush_support);
}
}

View File

@ -12,7 +12,7 @@
*/
/* Genode includes */
#include <base/printf.h>
#include <base/log.h>
/* core includes */
#include <ram_session_component.h>
@ -43,14 +43,18 @@ void Ram_session_component::_clear_ds (Dataspace_component *ds)
/* allocate range in core's virtual address space */
void *virt_addr;
if (!platform()->region_alloc()->alloc(page_rounded_size, &virt_addr)) {
PERR("could not allocate virtual address range in core of size %zd\n",
page_rounded_size);
error("could not allocate virtual address range in core of size ",
page_rounded_size);
return;
}
/* map the dataspace's physical pages to core-local virtual addresses */
size_t num_pages = page_rounded_size >> get_page_size_log2();
map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages);
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages)) {
error("could not map virtual address range in core of size ",
page_rounded_size);
return;
}
/* clear dataspace */
size_t num_longwords = page_rounded_size/sizeof(long);