mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 15:02:25 +00:00
hw: replace page table allocator with static one
Instead of organizing page tables within slab blocks and allocating such blocks dynamically on demand, replace the page table allocator with a simple, static alternative. The new page table allocator is dimensioned at compile-time. When a PD runs out of page-tables, we simply flush its current mappings, and re-use the freed tables. The only exception is core/kernel that should not produce any page faults. Thereby it has to be ensured that core has enough page tables to populate it's virtual memory. A positive side-effect of this static approach is that the accounting of memory used for page-tables is now possible again. In the dynamic case there was no protocol existent that solved the problem of donating memory to core during a page fault. Fix #1588
This commit is contained in:
parent
3291ca59a3
commit
cc58b11998
@ -16,7 +16,10 @@
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
enum { DEFAULT_STACK_SIZE = 16 * 1024 };
|
||||
enum {
|
||||
DEFAULT_STACK_SIZE = 16 * 1024,
|
||||
DEFAULT_TRANSLATION_TABLE_MAX = 128,
|
||||
};
|
||||
|
||||
/* amount of priority bands amongst quota owners in CPU scheduling */
|
||||
constexpr unsigned cpu_priorities = 4;
|
||||
|
@ -1,83 +0,0 @@
|
||||
/**
|
||||
* \brief Tools for early translation tables
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \date 2014-08-05
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _KERNEL__EARLY_TRANSLATIONS_H_
|
||||
#define _KERNEL__EARLY_TRANSLATIONS_H_
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <page_slab.h>
|
||||
#include <translation_table.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Dummy back-end allocator for early translation tables
|
||||
*/
|
||||
class Early_translations_allocator;
|
||||
|
||||
/**
|
||||
* Aligned slab for early translation tables
|
||||
*/
|
||||
class Early_translations_slab;
|
||||
}
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
using Genode::Early_translations_allocator;
|
||||
using Genode::Early_translations_slab;
|
||||
}
|
||||
|
||||
class Genode::Early_translations_allocator : public Genode::Core_mem_translator
|
||||
{
|
||||
public:
|
||||
|
||||
Early_translations_allocator() { }
|
||||
int add_range(addr_t base, size_t size) override { return -1; }
|
||||
int remove_range(addr_t base, size_t size) override { return -1; }
|
||||
Alloc_return alloc_aligned(size_t, void **, int, addr_t, addr_t) override {
|
||||
return Alloc_return::RANGE_CONFLICT; }
|
||||
Alloc_return alloc_addr(size_t size, addr_t addr) override {
|
||||
return Alloc_return::RANGE_CONFLICT; }
|
||||
void free(void *addr) override { }
|
||||
size_t avail() const override { return 0; }
|
||||
bool valid_addr(addr_t addr) const override { return false; }
|
||||
bool alloc(size_t size, void **out_addr) override { return false; }
|
||||
void free(void *addr, size_t) override { }
|
||||
size_t overhead(size_t size) const override { return 0; }
|
||||
bool need_size_for_free() const override { return false; }
|
||||
void * phys_addr(void * addr) { return addr; }
|
||||
void * virt_addr(void * addr) { return addr; }
|
||||
};
|
||||
|
||||
class Genode::Early_translations_slab : public Genode::Page_slab
|
||||
{
|
||||
public:
|
||||
|
||||
typedef Genode::Core_mem_translator Allocator;
|
||||
|
||||
enum {
|
||||
ALIGN_LOG2 = Genode::Translation_table::ALIGNM_LOG2,
|
||||
ALIGN = 1 << ALIGN_LOG2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Early_translations_slab(Allocator * const alloc) : Page_slab(alloc) {
|
||||
assert(Genode::aligned(this, ALIGN_LOG2)); }
|
||||
|
||||
} __attribute__((aligned(Early_translations_slab::ALIGN)));
|
||||
|
||||
#endif /* _KERNEL__EARLY_TRANSLATIONS_H_ */
|
@ -16,12 +16,11 @@
|
||||
#define _KERNEL__PD_H_
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/early_translations.h>
|
||||
#include <translation_table.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/object.h>
|
||||
|
||||
namespace Genode {
|
||||
class Page_slab;
|
||||
class Platform_pd;
|
||||
}
|
||||
|
||||
@ -56,13 +55,15 @@ class Kernel::Mode_transition_control
|
||||
|
||||
private:
|
||||
|
||||
typedef Early_translations_allocator Allocator;
|
||||
typedef Early_translations_slab Slab;
|
||||
typedef Genode::Translation_table Table;
|
||||
typedef Genode::Page_flags Page_flags;
|
||||
/*
|
||||
* set the table allocator to the current minimum of bits-of-one-mword
|
||||
* this is a limitation of the Bit_allocator used within this allocator.
|
||||
* actually only one page-mapping is needed by the MTC allocator
|
||||
*/
|
||||
typedef Genode::Translation_table_allocator_tpl<64> Allocator;
|
||||
typedef Genode::Translation_table Table;
|
||||
|
||||
Allocator _allocator;
|
||||
Slab _slab;
|
||||
Allocator _alloc;
|
||||
Table _table;
|
||||
Cpu_context _master;
|
||||
|
||||
@ -100,11 +101,11 @@ class Kernel::Mode_transition_control
|
||||
/**
|
||||
* Map the mode transition page to a virtual address space
|
||||
*
|
||||
* \param tt translation buffer of the address space
|
||||
* \param ram RAM donation for mapping (first try without)
|
||||
* \param tt translation buffer of the address space
|
||||
* \param alloc translation table allocator used for the mapping
|
||||
*/
|
||||
void map(Genode::Translation_table * tt,
|
||||
Genode::Page_slab * alloc);
|
||||
Genode::Translation_table_allocator * alloc);
|
||||
|
||||
/**
|
||||
* Continue execution of client context
|
||||
|
@ -1,230 +0,0 @@
|
||||
/*
|
||||
* \brief Slab allocator with aligned slab entries
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-03-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__PAGE_SLAB_H_
|
||||
#define _CORE__INCLUDE__PAGE_SLAB_H_
|
||||
|
||||
#include <base/allocator.h>
|
||||
#include <base/stdint.h>
|
||||
#include <util/list.h>
|
||||
#include <util/bit_allocator.h>
|
||||
#include <util/construct_at.h>
|
||||
|
||||
#include <core_mem_alloc.h>
|
||||
|
||||
namespace Genode {
|
||||
class Page_slab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Slab allocator returning aligned slab entries for page table descriptors.
|
||||
*/
|
||||
class Genode::Page_slab : public Genode::Allocator
|
||||
{
|
||||
protected:
|
||||
|
||||
static constexpr unsigned MIN_SLABS = 6;
|
||||
static constexpr unsigned SLAB_SIZE = get_page_size();
|
||||
static constexpr unsigned SLABS_PER_BLOCK = 8 * sizeof(addr_t);
|
||||
static constexpr unsigned ALIGN_LOG2 = get_page_size_log2();
|
||||
|
||||
/**
|
||||
* A slab block holding a fixed amount of slabs
|
||||
*/
|
||||
struct Slab_block
|
||||
{
|
||||
uint8_t data[SLAB_SIZE*SLABS_PER_BLOCK];
|
||||
Bit_allocator<SLABS_PER_BLOCK> indices;
|
||||
List_element<Slab_block> list_elem;
|
||||
size_t ref_counter;
|
||||
|
||||
Slab_block() : list_elem(this), ref_counter(0) {}
|
||||
|
||||
/**
|
||||
* Alloc a free block
|
||||
*/
|
||||
void* alloc()
|
||||
{
|
||||
ref_counter++;
|
||||
size_t off = indices.alloc() * SLAB_SIZE;
|
||||
return (void*)((Genode::addr_t)&data + off);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free given slab
|
||||
*
|
||||
* \param addr address of slab to free
|
||||
* \return true if slab is part of this block, and got freed
|
||||
*/
|
||||
bool free(void *addr)
|
||||
{
|
||||
if (addr < &data || addr > &indices) return false;
|
||||
ref_counter--;
|
||||
size_t off = (addr_t)addr - (addr_t)&data;
|
||||
indices.free(off / SLAB_SIZE);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Slab_block _initial_sb __attribute__((aligned(1 << ALIGN_LOG2))); /*
|
||||
first slab block is part of allocator to solve hen-egg problems */
|
||||
|
||||
List<List_element<Slab_block> > _b_list; /* list of slab blocks */
|
||||
Core_mem_translator *_backing_store; /* block allocator */
|
||||
size_t _free_slab_entries; /* free slabs */
|
||||
bool _in_alloc; /* in block allocation */
|
||||
|
||||
/**
|
||||
* Frees a given slab block
|
||||
*
|
||||
* \param b address of slab block to free
|
||||
*/
|
||||
void _free_slab_block(Slab_block * b)
|
||||
{
|
||||
if (b == &_initial_sb) return;
|
||||
|
||||
_b_list.remove(&b->list_elem);
|
||||
destroy(_backing_store, b);
|
||||
_free_slab_entries -= SLABS_PER_BLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns number of used slab blocks
|
||||
*/
|
||||
size_t _slab_blocks_in_use() const
|
||||
{
|
||||
size_t cnt = 0;
|
||||
for (List_element<Slab_block> const *le = _b_list.first();
|
||||
le; le = le->next(), cnt++) ;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
class Out_of_slabs {};
|
||||
|
||||
static constexpr size_t SLAB_BLOCK_SIZE = sizeof(Slab_block);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param backing_store allocator for additional slab blocks
|
||||
*/
|
||||
Page_slab(Core_mem_translator *backing_store)
|
||||
: _backing_store(backing_store), _free_slab_entries(SLABS_PER_BLOCK),
|
||||
_in_alloc(false) { _b_list.insert(&_initial_sb.list_elem); }
|
||||
|
||||
~Page_slab()
|
||||
{
|
||||
while (_b_list.first() && (_b_list.first() != &_initial_sb.list_elem))
|
||||
_free_slab_block(_b_list.first()->object());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set allocator used for slab blocks
|
||||
*/
|
||||
void backing_store(Core_mem_translator *cma) { _backing_store = cma; }
|
||||
|
||||
/**
|
||||
* Allocate additional slab blocks
|
||||
*
|
||||
* \throw Out_of_memory when no slab block could be allocated
|
||||
*/
|
||||
void alloc_slab_block()
|
||||
{
|
||||
void *p;
|
||||
if (!_backing_store->alloc_aligned(sizeof(Slab_block), &p,
|
||||
ALIGN_LOG2).is_ok()) {
|
||||
throw Out_of_memory();
|
||||
}
|
||||
Slab_block *b = Genode::construct_at<Slab_block>(p);
|
||||
_b_list.insert(&b->list_elem);
|
||||
_free_slab_entries += SLABS_PER_BLOCK;
|
||||
_in_alloc = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a slab
|
||||
*
|
||||
* \throw Out_of_slabs when new slab blocks need to be allocated
|
||||
* \returns pointer to new slab, or zero if allocation failed
|
||||
*/
|
||||
void *alloc()
|
||||
{
|
||||
if (_free_slab_entries <= MIN_SLABS && !_in_alloc) {
|
||||
_in_alloc = true;
|
||||
throw Out_of_slabs();
|
||||
}
|
||||
|
||||
void * ret = 0;
|
||||
for (List_element<Slab_block> *le = _b_list.first();
|
||||
le; le = le->next()) {
|
||||
if (le->object()->ref_counter == SLABS_PER_BLOCK)
|
||||
continue;
|
||||
|
||||
ret = le->object()->alloc();
|
||||
_free_slab_entries--;
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a given slab
|
||||
*
|
||||
* As a side effect empty slab block might get freed
|
||||
*
|
||||
* \param addr address of slab to free
|
||||
*/
|
||||
void free(void *addr)
|
||||
{
|
||||
for (List_element<Slab_block> *le = _b_list.first(); le;) {
|
||||
List_element<Slab_block> *cur = le;
|
||||
le = le->next();
|
||||
if (!cur->object()->free(addr)) continue;
|
||||
|
||||
if (_free_slab_entries++ > (MIN_SLABS+SLABS_PER_BLOCK)
|
||||
&& !cur->object()->ref_counter)
|
||||
_free_slab_block(cur->object());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return physical address of given slab address
|
||||
*
|
||||
* \param addr slab address
|
||||
*/
|
||||
void * phys_addr(void * addr) {
|
||||
return _backing_store->phys_addr(addr); }
|
||||
|
||||
/**
|
||||
* Return slab address of given physical address
|
||||
*
|
||||
* \param addr physical address
|
||||
*/
|
||||
void * virt_addr(void * addr) {
|
||||
return _backing_store->virt_addr(addr); }
|
||||
|
||||
|
||||
/************************
|
||||
* Allocator interface **
|
||||
************************/
|
||||
|
||||
bool alloc(size_t, void **addr) override { return (*addr = alloc()); }
|
||||
void free(void *addr, size_t) override { free(addr); }
|
||||
size_t consumed() const override { return SLAB_BLOCK_SIZE * _slab_blocks_in_use(); }
|
||||
size_t overhead(size_t) const override { return SLAB_BLOCK_SIZE/SLABS_PER_BLOCK; }
|
||||
bool need_size_for_free() const override { return false; }
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__PAGE_SLAB_H_ */
|
@ -19,13 +19,17 @@
|
||||
#include <translation_table.h>
|
||||
#include <platform.h>
|
||||
#include <address_space.h>
|
||||
#include <page_slab.h>
|
||||
#include <translation_table_allocator.h>
|
||||
#include <object.h>
|
||||
#include <kernel/configuration.h>
|
||||
#include <kernel/object.h>
|
||||
#include <kernel/pd.h>
|
||||
|
||||
namespace Hw
|
||||
{
|
||||
using namespace Kernel;
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* Memory virtualization interface of a protection domain
|
||||
*/
|
||||
@ -57,14 +61,17 @@ class Hw::Address_space : public Genode::Address_space
|
||||
friend class Genode::Platform;
|
||||
friend class Genode::Core_mem_allocator::Mapped_mem_allocator;
|
||||
|
||||
Genode::Lock _lock; /* table lock */
|
||||
Genode::Translation_table * _tt; /* table virtual addr. */
|
||||
Genode::Translation_table * _tt_phys; /* table physical addr. */
|
||||
Genode::Page_slab * _pslab; /* page table allocator */
|
||||
Kernel::Pd * _kernel_pd;
|
||||
using Table_allocator =
|
||||
Translation_table_allocator_tpl<DEFAULT_TRANSLATION_TABLE_MAX>;
|
||||
|
||||
Genode::Lock _lock; /* table lock */
|
||||
Genode::Translation_table * _tt; /* table virt addr */
|
||||
Genode::Translation_table * _tt_phys; /* table phys addr */
|
||||
Genode::Translation_table_allocator * _tt_alloc; /* table allocator */
|
||||
Kernel::Pd * _kernel_pd;
|
||||
|
||||
static inline Genode::Core_mem_allocator * _cma();
|
||||
static inline void * _tt_alloc();
|
||||
static inline void * _table_alloc();
|
||||
|
||||
protected:
|
||||
|
||||
@ -72,13 +79,13 @@ class Hw::Address_space : public Genode::Address_space
|
||||
/**
|
||||
* Core-specific constructor
|
||||
*
|
||||
* \param pd pointer to kernel's pd object
|
||||
* \param tt pointer to translation table
|
||||
* \param slab pointer to page slab allocator
|
||||
* \param pd pointer to kernel's pd object
|
||||
* \param tt pointer to translation table
|
||||
* \param tt_alloc pointer to translation table allocator
|
||||
*/
|
||||
Address_space(Kernel::Pd * pd,
|
||||
Genode::Translation_table * tt,
|
||||
Genode::Page_slab * slab);
|
||||
Address_space(Kernel::Pd * pd,
|
||||
Genode::Translation_table * tt,
|
||||
Genode::Translation_table_allocator * tt_alloc);
|
||||
|
||||
public:
|
||||
|
||||
@ -158,10 +165,11 @@ class Genode::Platform_pd : public Hw::Address_space,
|
||||
/**
|
||||
* Constructor for core pd
|
||||
*
|
||||
* \param tt translation table address
|
||||
* \param slab page table allocator
|
||||
* \param tt translation table address
|
||||
* \param tt_alloc translation table allocator
|
||||
*/
|
||||
Platform_pd(Translation_table * tt, Page_slab * slab);
|
||||
Platform_pd(Translation_table * tt,
|
||||
Translation_table_allocator * tt_alloc);
|
||||
|
||||
public:
|
||||
|
||||
@ -205,8 +213,8 @@ class Genode::Core_platform_pd : public Genode::Platform_pd
|
||||
{
|
||||
private:
|
||||
|
||||
static inline Translation_table * const _table();
|
||||
static inline Page_slab * const _slab();
|
||||
static inline Translation_table * const _table();
|
||||
static inline Translation_table_allocator * const _table_alloc();
|
||||
|
||||
/**
|
||||
* Establish initial one-to-one mappings for core/kernel.
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <util.h>
|
||||
#include <assert.h>
|
||||
#include <page_flags.h>
|
||||
#include <page_slab.h>
|
||||
#include <translation_table_allocator.h>
|
||||
#include <cpu.h>
|
||||
|
||||
namespace Genode
|
||||
@ -412,22 +412,22 @@ class Genode::Translation_table
|
||||
* \param pa physical start address of range
|
||||
* \param size size of range
|
||||
* \param flags mapping flags
|
||||
* \param slab second level page slab allocator
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void _insert_second_level(unsigned i, addr_t const vo, addr_t const pa,
|
||||
size_t const size, Page_flags const & flags,
|
||||
Page_slab * const slab)
|
||||
Translation_table_allocator * const alloc)
|
||||
{
|
||||
Page_table * pt = 0;
|
||||
switch (Descriptor::type(_entries[i])) {
|
||||
|
||||
case Descriptor::FAULT:
|
||||
{
|
||||
if (!slab) throw Allocator::Out_of_memory();
|
||||
if (!alloc) throw Allocator::Out_of_memory();
|
||||
|
||||
/* create and link page table */
|
||||
pt = new (slab) Page_table();
|
||||
Page_table * pt_phys = (Page_table*) slab->phys_addr(pt);
|
||||
pt = new (alloc) Page_table();
|
||||
Page_table * pt_phys = (Page_table*) alloc->phys_addr(pt);
|
||||
pt_phys = pt_phys ? pt_phys : pt; /* hack for core */
|
||||
_entries[i] = Page_table_descriptor::create(pt_phys);
|
||||
|
||||
@ -441,7 +441,7 @@ class Genode::Translation_table
|
||||
/* use allocator to retrieve virtual addr. of page table */
|
||||
void * pt_phys = (void*)
|
||||
Page_table_descriptor::Pa::masked(_entries[i]);
|
||||
pt = (Page_table *) slab->virt_addr(pt_phys);
|
||||
pt = (Page_table *) alloc->virt_addr(pt_phys);
|
||||
pt = pt ? pt : (Page_table *)pt_phys ; /* hack for core */
|
||||
break;
|
||||
}
|
||||
@ -481,10 +481,11 @@ class Genode::Translation_table
|
||||
* \param pa base of physical backing store
|
||||
* \param size size of translated region
|
||||
* \param f mapping flags
|
||||
* \param s second level page slab allocator
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void insert_translation(addr_t vo, addr_t pa, size_t size,
|
||||
Page_flags const & f, Page_slab * const s)
|
||||
Page_flags const & f,
|
||||
Translation_table_allocator * const alloc)
|
||||
{
|
||||
/* check sanity */
|
||||
assert(!(vo & Page_table::Descriptor::VIRT_OFFSET_MASK) &&
|
||||
@ -515,7 +516,8 @@ class Genode::Translation_table
|
||||
}
|
||||
|
||||
default:
|
||||
_insert_second_level(i, vo, pa, min(size, end - vo), f, s);
|
||||
_insert_second_level(i, vo, pa, min(size, end - vo), f,
|
||||
alloc);
|
||||
};
|
||||
|
||||
/* check whether we wrap */
|
||||
@ -533,9 +535,10 @@ class Genode::Translation_table
|
||||
*
|
||||
* \param vo region offset within the tables virtual region
|
||||
* \param size region size
|
||||
* \param slab second level page slab allocator
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void remove_translation(addr_t vo, size_t size, Page_slab * slab)
|
||||
void remove_translation(addr_t vo, size_t size,
|
||||
Translation_table_allocator * alloc)
|
||||
{
|
||||
/* check sanity */
|
||||
assert(vo <= (vo + size));
|
||||
@ -553,7 +556,7 @@ class Genode::Translation_table
|
||||
typedef Page_table Pt;
|
||||
|
||||
Pt * pt_phys = (Pt *) Ptd::Pa::masked(_entries[i]);
|
||||
Pt * pt = (Pt *) slab->virt_addr(pt_phys);
|
||||
Pt * pt = (Pt *) alloc->virt_addr(pt_phys);
|
||||
pt = pt ? pt : pt_phys; // TODO hack for core
|
||||
|
||||
addr_t const pt_vo = vo - Section::Pa::masked(vo);
|
||||
@ -561,7 +564,7 @@ class Genode::Translation_table
|
||||
|
||||
if (pt->empty()) {
|
||||
Descriptor::invalidate(_entries[i]);
|
||||
destroy(slab, pt);
|
||||
destroy(alloc, pt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
/* base-hw includes */
|
||||
#include <page_flags.h>
|
||||
#include <page_slab.h>
|
||||
#include <translation_table_allocator.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
@ -324,11 +324,12 @@ class Genode::Level_3_translation_table :
|
||||
|
||||
struct Insert_func
|
||||
{
|
||||
Page_flags const & flags;
|
||||
Page_slab * slab;
|
||||
Page_flags const & flags;
|
||||
Translation_table_allocator * alloc;
|
||||
|
||||
Insert_func(Page_flags const & flags,
|
||||
Page_slab * slab) : flags(flags), slab(slab) { }
|
||||
Translation_table_allocator * alloc)
|
||||
: flags(flags), alloc(alloc) { }
|
||||
|
||||
void operator () (addr_t const vo,
|
||||
addr_t const pa,
|
||||
@ -354,9 +355,9 @@ class Genode::Level_3_translation_table :
|
||||
|
||||
struct Remove_func
|
||||
{
|
||||
Page_slab * slab;
|
||||
Translation_table_allocator * alloc;
|
||||
|
||||
Remove_func(Page_slab * slab) : slab(slab) { }
|
||||
Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { }
|
||||
|
||||
void operator () (addr_t const vo,
|
||||
addr_t const pa,
|
||||
@ -371,11 +372,12 @@ class Genode::Level_3_translation_table :
|
||||
addr_t pa,
|
||||
size_t size,
|
||||
Page_flags const & flags,
|
||||
Page_slab * slab) {
|
||||
_range_op(vo, pa, size, Insert_func(flags, slab)); }
|
||||
Translation_table_allocator * alloc) {
|
||||
_range_op(vo, pa, size, Insert_func(flags, alloc)); }
|
||||
|
||||
void remove_translation(addr_t vo, size_t size, Page_slab * slab) {
|
||||
_range_op(vo, 0, size, Remove_func(slab)); }
|
||||
void remove_translation(addr_t vo, size_t size,
|
||||
Translation_table_allocator * alloc) {
|
||||
_range_op(vo, 0, size, Remove_func(alloc)); }
|
||||
};
|
||||
|
||||
|
||||
@ -392,11 +394,12 @@ class Genode::Level_x_translation_table :
|
||||
|
||||
struct Insert_func
|
||||
{
|
||||
Page_flags const & flags;
|
||||
Page_slab * slab;
|
||||
Page_flags const & flags;
|
||||
Translation_table_allocator * alloc;
|
||||
|
||||
Insert_func(Page_flags const & flags,
|
||||
Page_slab * slab) : flags(flags), slab(slab) { }
|
||||
Translation_table_allocator * alloc)
|
||||
: flags(flags), alloc(alloc) { }
|
||||
|
||||
void operator () (addr_t const vo,
|
||||
addr_t const pa,
|
||||
@ -420,11 +423,11 @@ class Genode::Level_x_translation_table :
|
||||
|
||||
case Descriptor::INVALID: /* no entry */
|
||||
{
|
||||
if (!slab) throw Allocator::Out_of_memory();
|
||||
if (!alloc) throw Allocator::Out_of_memory();
|
||||
|
||||
/* create and link next level table */
|
||||
table = new (slab) ENTRY();
|
||||
ENTRY * phys_addr = (ENTRY*) slab->phys_addr(table);
|
||||
table = new (alloc) ENTRY();
|
||||
ENTRY * phys_addr = (ENTRY*) alloc->phys_addr(table);
|
||||
desc = Table_descriptor::create(phys_addr ?
|
||||
phys_addr : table);
|
||||
}
|
||||
@ -434,7 +437,7 @@ class Genode::Level_x_translation_table :
|
||||
/* use allocator to retrieve virt address of table */
|
||||
ENTRY * phys_addr = (ENTRY*)
|
||||
Table_descriptor::Next_table::masked(desc);
|
||||
table = (ENTRY*) slab->virt_addr(phys_addr);
|
||||
table = (ENTRY*) alloc->virt_addr(phys_addr);
|
||||
table = table ? table : (ENTRY*)phys_addr;
|
||||
break;
|
||||
}
|
||||
@ -447,16 +450,16 @@ class Genode::Level_x_translation_table :
|
||||
|
||||
/* insert translation */
|
||||
table->insert_translation(vo - (vo & Base::BLOCK_MASK),
|
||||
pa, size, flags, slab);
|
||||
pa, size, flags, alloc);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Remove_func
|
||||
{
|
||||
Page_slab * slab;
|
||||
Translation_table_allocator * alloc;
|
||||
|
||||
Remove_func(Page_slab * slab) : slab(slab) { }
|
||||
Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { }
|
||||
|
||||
void operator () (addr_t const vo,
|
||||
addr_t const pa,
|
||||
@ -469,13 +472,13 @@ class Genode::Level_x_translation_table :
|
||||
/* use allocator to retrieve virt address of table */
|
||||
ENTRY * phys_addr = (ENTRY*)
|
||||
Table_descriptor::Next_table::masked(desc);
|
||||
ENTRY * table = (ENTRY*) slab->virt_addr(phys_addr);
|
||||
ENTRY * table = (ENTRY*) alloc->virt_addr(phys_addr);
|
||||
table = table ? table : (ENTRY*)phys_addr;
|
||||
table->remove_translation(vo - (vo & Base::BLOCK_MASK),
|
||||
size, slab);
|
||||
size, alloc);
|
||||
if (!table->empty())
|
||||
break;
|
||||
destroy(slab, table);
|
||||
destroy(alloc, table);
|
||||
}
|
||||
case Descriptor::BLOCK:
|
||||
case Descriptor::INVALID:
|
||||
@ -492,30 +495,31 @@ class Genode::Level_x_translation_table :
|
||||
/**
|
||||
* Insert translations into this table
|
||||
*
|
||||
* \param vo offset of the virtual region represented
|
||||
* by the translation within the virtual
|
||||
* region represented by this table
|
||||
* \param pa base of the physical backing store
|
||||
* \param size size of the translated region
|
||||
* \param flags mapping flags
|
||||
* \param slab second level page slab allocator
|
||||
* \param vo offset of the virtual region represented
|
||||
* by the translation within the virtual
|
||||
* region represented by this table
|
||||
* \param pa base of the physical backing store
|
||||
* \param size size of the translated region
|
||||
* \param flags mapping flags
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void insert_translation(addr_t vo,
|
||||
addr_t pa,
|
||||
size_t size,
|
||||
Page_flags const & flags,
|
||||
Page_slab * slab) {
|
||||
this->_range_op(vo, pa, size, Insert_func(flags, slab)); }
|
||||
Translation_table_allocator * alloc) {
|
||||
this->_range_op(vo, pa, size, Insert_func(flags, alloc)); }
|
||||
|
||||
/**
|
||||
* Remove translations that overlap with a given virtual region
|
||||
*
|
||||
* \param vo region offset within the tables virtual region
|
||||
* \param size region size
|
||||
* \param slab second level page slab allocator
|
||||
* \param vo region offset within the tables virtual region
|
||||
* \param size region size
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void remove_translation(addr_t vo, size_t size, Page_slab * slab) {
|
||||
this->_range_op(vo, 0, size, Remove_func(slab)); }
|
||||
void remove_translation(addr_t vo, size_t size,
|
||||
Translation_table_allocator * alloc) {
|
||||
this->_range_op(vo, 0, size, Remove_func(alloc)); }
|
||||
};
|
||||
|
||||
namespace Genode {
|
||||
|
@ -38,14 +38,16 @@ class Genode::Vm_session_component
|
||||
|
||||
using Translation_table =
|
||||
Genode::Level_1_stage_2_translation_table;
|
||||
using Table_allocator = Translation_table_allocator_tpl<
|
||||
Kernel::DEFAULT_TRANSLATION_TABLE_MAX>;
|
||||
|
||||
Rpc_entrypoint *_ds_ep;
|
||||
Range_allocator *_ram_alloc;
|
||||
Dataspace_component _ds;
|
||||
Dataspace_capability _ds_cap;
|
||||
addr_t _ds_addr;
|
||||
Translation_table *_table;
|
||||
Page_slab *_pslab;
|
||||
Rpc_entrypoint *_ds_ep;
|
||||
Range_allocator *_ram_alloc;
|
||||
Dataspace_component _ds;
|
||||
Dataspace_capability _ds_cap;
|
||||
addr_t _ds_addr;
|
||||
Translation_table *_table;
|
||||
Translation_table_allocator *_tt_alloc;
|
||||
|
||||
static size_t _ds_size() {
|
||||
return align_addr(sizeof(Cpu_state_modes),
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
/* base-hw includes */
|
||||
#include <page_flags.h>
|
||||
#include <page_slab.h>
|
||||
#include <translation_table_allocator.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
@ -152,11 +152,12 @@ class Genode::Level_4_translation_table
|
||||
|
||||
struct Insert_func
|
||||
{
|
||||
Page_flags const & flags;
|
||||
Page_slab * slab;
|
||||
Page_flags const & flags;
|
||||
Translation_table_allocator * alloc;
|
||||
|
||||
Insert_func(Page_flags const & flags,
|
||||
Page_slab * slab) : flags(flags), slab(slab) { }
|
||||
Translation_table_allocator * alloc)
|
||||
: flags(flags), alloc(alloc) { }
|
||||
|
||||
void operator () (addr_t const vo, addr_t const pa,
|
||||
size_t const size,
|
||||
@ -181,9 +182,9 @@ class Genode::Level_4_translation_table
|
||||
|
||||
struct Remove_func
|
||||
{
|
||||
Page_slab * slab;
|
||||
Translation_table_allocator * alloc;
|
||||
|
||||
Remove_func(Page_slab * slab) : slab(slab) { }
|
||||
Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { }
|
||||
|
||||
void operator () (addr_t const vo, addr_t const pa,
|
||||
size_t const size,
|
||||
@ -247,12 +248,13 @@ class Genode::Level_4_translation_table
|
||||
* \param pa base of the physical backing store
|
||||
* \param size size of the translated region
|
||||
* \param flags mapping flags
|
||||
* \param slab second level page slab allocator
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void insert_translation(addr_t vo, addr_t pa, size_t size,
|
||||
Page_flags const & flags, Page_slab * slab)
|
||||
Page_flags const & flags,
|
||||
Translation_table_allocator * alloc)
|
||||
{
|
||||
this->_range_op(vo, pa, size, Insert_func(flags, slab));
|
||||
this->_range_op(vo, pa, size, Insert_func(flags, alloc));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,11 +262,12 @@ class Genode::Level_4_translation_table
|
||||
*
|
||||
* \param vo region offset within the tables virtual region
|
||||
* \param size region size
|
||||
* \param slab second level page slab allocator
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void remove_translation(addr_t vo, size_t size, Page_slab * slab)
|
||||
void remove_translation(addr_t vo, size_t size,
|
||||
Translation_table_allocator * alloc)
|
||||
{
|
||||
this->_range_op(vo, 0, size, Remove_func(slab));
|
||||
this->_range_op(vo, 0, size, Remove_func(alloc));
|
||||
}
|
||||
} __attribute__((aligned(1 << ALIGNM_LOG2)));
|
||||
|
||||
@ -355,11 +358,12 @@ class Genode::Page_directory
|
||||
|
||||
struct Insert_func
|
||||
{
|
||||
Page_flags const & flags;
|
||||
Page_slab * slab;
|
||||
Page_flags const & flags;
|
||||
Translation_table_allocator * alloc;
|
||||
|
||||
Insert_func(Page_flags const & flags,
|
||||
Page_slab * slab) : flags(flags), slab(slab) { }
|
||||
Translation_table_allocator * alloc)
|
||||
: flags(flags), alloc(alloc) { }
|
||||
|
||||
void operator () (addr_t const vo, addr_t const pa,
|
||||
size_t const size,
|
||||
@ -385,12 +389,12 @@ class Genode::Page_directory
|
||||
/* we need to use a next level table */
|
||||
ENTRY *table;
|
||||
if (!Base_descriptor::present(desc)) {
|
||||
if (!slab)
|
||||
if (!alloc)
|
||||
throw Allocator::Out_of_memory();
|
||||
|
||||
/* create and link next level table */
|
||||
table = new (slab) ENTRY();
|
||||
ENTRY * phys_addr = (ENTRY*) slab->phys_addr(table);
|
||||
table = new (alloc) ENTRY();
|
||||
ENTRY * phys_addr = (ENTRY*) alloc->phys_addr(table);
|
||||
addr_t const pa = (addr_t)(phys_addr ? phys_addr : table);
|
||||
desc = (typename Base_descriptor::access_t)
|
||||
Table_descriptor::create(flags, pa);
|
||||
@ -401,21 +405,21 @@ class Genode::Page_directory
|
||||
Base_descriptor::merge_access_rights(desc, flags);
|
||||
ENTRY * phys_addr = (ENTRY*)
|
||||
Table_descriptor::Pa::masked(desc);
|
||||
table = (ENTRY*) slab->virt_addr(phys_addr);
|
||||
table = (ENTRY*) alloc->virt_addr(phys_addr);
|
||||
table = table ? table : (ENTRY*)phys_addr;
|
||||
}
|
||||
|
||||
/* insert translation */
|
||||
table->insert_translation(vo - (vo & PAGE_MASK),
|
||||
pa, size, flags, slab);
|
||||
pa, size, flags, alloc);
|
||||
}
|
||||
};
|
||||
|
||||
struct Remove_func
|
||||
{
|
||||
Page_slab * slab;
|
||||
Translation_table_allocator * alloc;
|
||||
|
||||
Remove_func(Page_slab * slab) : slab(slab) { }
|
||||
Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { }
|
||||
|
||||
void operator () (addr_t const vo, addr_t const pa,
|
||||
size_t const size,
|
||||
@ -428,12 +432,12 @@ class Genode::Page_directory
|
||||
/* use allocator to retrieve virt address of table */
|
||||
ENTRY* phys_addr = (ENTRY*)
|
||||
Table_descriptor::Pa::masked(desc);
|
||||
ENTRY* table = (ENTRY*) slab->virt_addr(phys_addr);
|
||||
ENTRY* table = (ENTRY*) alloc->virt_addr(phys_addr);
|
||||
table = table ? table : (ENTRY*)phys_addr;
|
||||
addr_t const table_vo = vo - (vo & PAGE_MASK);
|
||||
table->remove_translation(table_vo, size, slab);
|
||||
table->remove_translation(table_vo, size, alloc);
|
||||
if (table->empty()) {
|
||||
destroy(slab, table);
|
||||
destroy(alloc, table);
|
||||
desc = 0;
|
||||
}
|
||||
}
|
||||
@ -494,12 +498,13 @@ class Genode::Page_directory
|
||||
* \param pa base of the physical backing store
|
||||
* \param size size of the translated region
|
||||
* \param flags mapping flags
|
||||
* \param slab second level page slab allocator
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void insert_translation(addr_t vo, addr_t pa, size_t size,
|
||||
Page_flags const & flags, Page_slab * slab)
|
||||
Page_flags const & flags,
|
||||
Translation_table_allocator * alloc)
|
||||
{
|
||||
_range_op(vo, pa, size, Insert_func(flags, slab));
|
||||
_range_op(vo, pa, size, Insert_func(flags, alloc));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -507,11 +512,12 @@ class Genode::Page_directory
|
||||
*
|
||||
* \param vo region offset within the tables virtual region
|
||||
* \param size region size
|
||||
* \param slab second level page slab allocator
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void remove_translation(addr_t vo, size_t size, Page_slab * slab)
|
||||
void remove_translation(addr_t vo, size_t size,
|
||||
Translation_table_allocator * alloc)
|
||||
{
|
||||
_range_op(vo, 0, size, Remove_func(slab));
|
||||
_range_op(vo, 0, size, Remove_func(alloc));
|
||||
}
|
||||
} __attribute__((aligned(1 << ALIGNM_LOG2)));
|
||||
|
||||
@ -547,11 +553,12 @@ class Genode::Pml4_table
|
||||
|
||||
struct Insert_func
|
||||
{
|
||||
Page_flags const & flags;
|
||||
Page_slab * slab;
|
||||
Page_flags const & flags;
|
||||
Translation_table_allocator * alloc;
|
||||
|
||||
Insert_func(Page_flags const & flags,
|
||||
Page_slab * slab) : flags(flags), slab(slab) { }
|
||||
Translation_table_allocator * alloc)
|
||||
: flags(flags), alloc(alloc) { }
|
||||
|
||||
void operator () (addr_t const vo, addr_t const pa,
|
||||
size_t const size,
|
||||
@ -560,33 +567,33 @@ class Genode::Pml4_table
|
||||
/* we need to use a next level table */
|
||||
ENTRY *table;
|
||||
if (!Descriptor::present(desc)) {
|
||||
if (!slab)
|
||||
if (!alloc)
|
||||
throw Allocator::Out_of_memory();
|
||||
|
||||
/* create and link next level table */
|
||||
table = new (slab) ENTRY();
|
||||
ENTRY * phys_addr = (ENTRY*) slab->phys_addr(table);
|
||||
table = new (alloc) ENTRY();
|
||||
ENTRY * phys_addr = (ENTRY*) alloc->phys_addr(table);
|
||||
addr_t const pa = (addr_t)(phys_addr ? phys_addr : table);
|
||||
desc = Descriptor::create(flags, pa);
|
||||
} else {
|
||||
Descriptor::merge_access_rights(desc, flags);
|
||||
ENTRY * phys_addr = (ENTRY*)
|
||||
Descriptor::Pa::masked(desc);
|
||||
table = (ENTRY*) slab->virt_addr(phys_addr);
|
||||
table = (ENTRY*) alloc->virt_addr(phys_addr);
|
||||
table = table ? table : (ENTRY*)phys_addr;
|
||||
}
|
||||
|
||||
/* insert translation */
|
||||
addr_t const table_vo = vo - (vo & PAGE_MASK);
|
||||
table->insert_translation(table_vo, pa, size, flags, slab);
|
||||
table->insert_translation(table_vo, pa, size, flags, alloc);
|
||||
}
|
||||
};
|
||||
|
||||
struct Remove_func
|
||||
{
|
||||
Page_slab * slab;
|
||||
Translation_table_allocator * alloc;
|
||||
|
||||
Remove_func(Page_slab * slab) : slab(slab) { }
|
||||
Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { }
|
||||
|
||||
void operator () (addr_t const vo, addr_t const pa,
|
||||
size_t const size,
|
||||
@ -596,12 +603,12 @@ class Genode::Pml4_table
|
||||
/* use allocator to retrieve virt address of table */
|
||||
ENTRY* phys_addr = (ENTRY*)
|
||||
Descriptor::Pa::masked(desc);
|
||||
ENTRY* table = (ENTRY*) slab->virt_addr(phys_addr);
|
||||
ENTRY* table = (ENTRY*) alloc->virt_addr(phys_addr);
|
||||
table = table ? table : (ENTRY*)phys_addr;
|
||||
addr_t const table_vo = vo - (vo & PAGE_MASK);
|
||||
table->remove_translation(table_vo, size, slab);
|
||||
table->remove_translation(table_vo, size, alloc);
|
||||
if (table->empty()) {
|
||||
destroy(slab, table);
|
||||
destroy(alloc, table);
|
||||
desc = 0;
|
||||
}
|
||||
}
|
||||
@ -660,12 +667,13 @@ class Genode::Pml4_table
|
||||
* \param pa base of the physical backing store
|
||||
* \param size size of the translated region
|
||||
* \param flags mapping flags
|
||||
* \param slab second level page slab allocator
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void insert_translation(addr_t vo, addr_t pa, size_t size,
|
||||
Page_flags const & flags, Page_slab * slab)
|
||||
Page_flags const & flags,
|
||||
Translation_table_allocator * alloc)
|
||||
{
|
||||
_range_op(vo, pa, size, Insert_func(flags, slab));
|
||||
_range_op(vo, pa, size, Insert_func(flags, alloc));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -673,11 +681,12 @@ class Genode::Pml4_table
|
||||
*
|
||||
* \param vo region offset within the tables virtual region
|
||||
* \param size region size
|
||||
* \param slab second level page slab allocator
|
||||
* \param alloc second level translation table allocator
|
||||
*/
|
||||
void remove_translation(addr_t vo, size_t size, Page_slab * slab)
|
||||
void remove_translation(addr_t vo, size_t size,
|
||||
Translation_table_allocator * alloc)
|
||||
{
|
||||
_range_op(vo, 0, size, Remove_func(slab));
|
||||
_range_op(vo, 0, size, Remove_func(alloc));
|
||||
}
|
||||
} __attribute__((aligned(1 << ALIGNM_LOG2)));
|
||||
|
||||
|
161
repos/base-hw/src/core/include/translation_table_allocator.h
Normal file
161
repos/base-hw/src/core/include/translation_table_allocator.h
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* \brief Translation table allocator
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-06-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__TRANSLATION_TABLE_ALLOCATOR_H_
|
||||
#define _CORE__INCLUDE__TRANSLATION_TABLE_ALLOCATOR_H_
|
||||
|
||||
#include <base/native_types.h>
|
||||
#include <base/allocator.h>
|
||||
#include <util/bit_allocator.h>
|
||||
#include <base/stdint.h>
|
||||
#include <core_mem_alloc.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* Translation table allocator interface
|
||||
*/
|
||||
class Translation_table_allocator;
|
||||
|
||||
/**
|
||||
* Statically dimensioned translation table allocator
|
||||
*
|
||||
* /param TABLES count of tables the allocator provides as maximum
|
||||
*/
|
||||
template <unsigned TABLES> class Translation_table_allocator_tpl;
|
||||
}
|
||||
|
||||
|
||||
class Genode::Translation_table_allocator : public Genode::Allocator
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Return physical address of given virtual page address
|
||||
*
|
||||
* \param addr virtual page address
|
||||
*/
|
||||
virtual void * phys_addr(void * addr) = 0;
|
||||
|
||||
/**
|
||||
* Return virtual address of given physical page address
|
||||
*
|
||||
* \param addr physical page address
|
||||
*/
|
||||
virtual void * virt_addr(void * addr) = 0;
|
||||
};
|
||||
|
||||
|
||||
template <unsigned TABLES>
|
||||
class Genode::Translation_table_allocator_tpl
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* The actual allocator interface cannot be implmented by our
|
||||
* template class itself, because of its strict alignment constraints
|
||||
* and therefore the impossibility to have a vtable pointer at the
|
||||
* beginning of the object's layout. Therefore, we use a private
|
||||
* implementation of the interface and aggregate it.
|
||||
*/
|
||||
class Allocator;
|
||||
|
||||
struct Table { uint8_t data[get_page_size()]; };
|
||||
|
||||
Table _tables[TABLES];
|
||||
Allocator _alloc;
|
||||
|
||||
public:
|
||||
|
||||
static constexpr unsigned ALIGN= 1 << get_page_size_log2();
|
||||
|
||||
Translation_table_allocator_tpl() : _alloc(_tables, (addr_t)&_tables) {}
|
||||
Translation_table_allocator_tpl(Core_mem_allocator *cma)
|
||||
: _alloc(_tables, (addr_t)cma->phys_addr((void*)&_tables)) {}
|
||||
|
||||
Translation_table_allocator * alloc() { return &_alloc; }
|
||||
|
||||
static Translation_table_allocator_tpl *
|
||||
base(Translation_table_allocator * alloc)
|
||||
{
|
||||
return (Translation_table_allocator_tpl*)((addr_t)alloc
|
||||
- sizeof(Table)*TABLES);
|
||||
}
|
||||
} __attribute__((aligned(ALIGN)));
|
||||
|
||||
|
||||
template <unsigned TABLES>
|
||||
class Genode::Translation_table_allocator_tpl<TABLES>::Allocator
|
||||
: public Translation_table_allocator
|
||||
{
|
||||
private:
|
||||
|
||||
Table *_tables;
|
||||
Bit_allocator<TABLES> _free_tables;
|
||||
addr_t _phys_addr;
|
||||
|
||||
/**
|
||||
* Allocate a page
|
||||
*
|
||||
* \returns pointer to new slab, or nullptr if allocation failed
|
||||
*/
|
||||
void *_alloc()
|
||||
{
|
||||
try {
|
||||
return &_tables[_free_tables.alloc()];
|
||||
} catch(typename Bit_allocator<TABLES>::Out_of_indices&) {}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a given page
|
||||
*
|
||||
* \param addr virtual address of page to free
|
||||
*/
|
||||
void _free(void *addr)
|
||||
{
|
||||
_free_tables.free(((addr_t)addr - (addr_t)_tables)
|
||||
/ sizeof(Table));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Allocator(Table * tables, addr_t phys_addr)
|
||||
: _tables(tables), _phys_addr(phys_addr) {}
|
||||
|
||||
void * phys_addr(void * addr)
|
||||
{
|
||||
return (void*)((addr_t)addr - (addr_t)_tables
|
||||
+ _phys_addr);
|
||||
}
|
||||
|
||||
void * virt_addr(void * addr)
|
||||
{
|
||||
return (void*)((addr_t)_tables + ((addr_t)addr
|
||||
- _phys_addr));
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* Allocator interface **
|
||||
************************/
|
||||
|
||||
bool alloc(size_t, void **addr) override {
|
||||
return (*addr = _alloc()); }
|
||||
void free(void *addr, size_t) override { _free(addr); }
|
||||
size_t consumed() const override { return 0; }
|
||||
size_t overhead(size_t) const override { return 0; }
|
||||
bool need_size_for_free() const override { return false; }
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__TRANSLATION_TABLE_ALLOCATOR_H_ */
|
@ -17,6 +17,7 @@
|
||||
#include <base/native_types.h>
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <platform_pd.h>
|
||||
#include <kernel/ipc_node.h>
|
||||
#include <kernel/pd.h>
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <kernel/pd.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <assert.h>
|
||||
#include <page_flags.h>
|
||||
#include <unmanaged_singleton.h>
|
||||
|
||||
using namespace Kernel;
|
||||
@ -51,12 +53,12 @@ addr_t Mode_transition_control::_virt_user_entry()
|
||||
|
||||
|
||||
void Mode_transition_control::map(Genode::Translation_table * tt,
|
||||
Genode::Page_slab * alloc)
|
||||
Genode::Translation_table_allocator * alloc)
|
||||
{
|
||||
try {
|
||||
addr_t const phys_base = (addr_t)&_mt_begin;
|
||||
tt->insert_translation(VIRT_BASE, phys_base, SIZE,
|
||||
Page_flags::mode_transition(), alloc);
|
||||
Genode::Page_flags::mode_transition(), alloc);
|
||||
} catch(...) {
|
||||
PERR("Inserting exception vector in page table failed!"); }
|
||||
}
|
||||
@ -90,13 +92,12 @@ void Mode_transition_control::switch_to_user(Cpu::Context * const context,
|
||||
}
|
||||
|
||||
|
||||
Mode_transition_control::Mode_transition_control()
|
||||
: _slab(&_allocator), _master(&_table)
|
||||
Mode_transition_control::Mode_transition_control() : _master(&_table)
|
||||
{
|
||||
assert(Genode::aligned(this, ALIGN_LOG2));
|
||||
assert(sizeof(_master) <= _master_context_size());
|
||||
assert(_size() <= SIZE);
|
||||
map(&_table, &_slab);
|
||||
map(&_table, _alloc.alloc());
|
||||
Genode::memcpy(&_mt_master_context_begin, &_master, sizeof(_master));
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <util/construct_at.h>
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/irq.h>
|
||||
|
@ -19,10 +19,10 @@
|
||||
|
||||
/* core includes */
|
||||
#include <core_parent.h>
|
||||
#include <page_slab.h>
|
||||
#include <map_local.h>
|
||||
#include <platform.h>
|
||||
#include <platform_pd.h>
|
||||
#include <page_flags.h>
|
||||
#include <util.h>
|
||||
#include <pic.h>
|
||||
#include <kernel/kernel.h>
|
||||
@ -106,7 +106,6 @@ static Native_region * virt_region(unsigned const i) {
|
||||
static Native_region r = { VIRT_ADDR_SPACE_START, VIRT_ADDR_SPACE_SIZE };
|
||||
return i ? 0 : &r; }
|
||||
|
||||
static Core_mem_allocator * _core_mem_allocator = 0;
|
||||
|
||||
Platform::Platform()
|
||||
:
|
||||
@ -115,10 +114,6 @@ Platform::Platform()
|
||||
_irq_alloc(core_mem_alloc()),
|
||||
_vm_start(VIRT_ADDR_SPACE_START), _vm_size(VIRT_ADDR_SPACE_SIZE)
|
||||
{
|
||||
static Page_slab pslab(&_core_mem_alloc);
|
||||
Kernel::core_pd()->platform_pd()->_pslab = &pslab;
|
||||
_core_mem_allocator = &_core_mem_alloc;
|
||||
|
||||
/*
|
||||
* Initialise platform resource allocators.
|
||||
* Core mem alloc must come first because it is
|
||||
@ -213,22 +208,10 @@ bool Genode::unmap_local(addr_t virt_addr, size_t num_pages)
|
||||
|
||||
bool Core_mem_allocator::Mapped_mem_allocator::_map_local(addr_t virt_addr,
|
||||
addr_t phys_addr,
|
||||
unsigned size)
|
||||
{
|
||||
Genode::Page_slab * slab = Kernel::core_pd()->platform_pd()->_pslab;
|
||||
slab->backing_store(_core_mem_allocator->raw());
|
||||
bool ret = ::map_local(phys_addr, virt_addr, size / get_page_size());
|
||||
slab->backing_store(_core_mem_allocator);
|
||||
return ret;
|
||||
}
|
||||
unsigned size) {
|
||||
return ::map_local(phys_addr, virt_addr, size / get_page_size()); }
|
||||
|
||||
|
||||
bool Core_mem_allocator::Mapped_mem_allocator::_unmap_local(addr_t virt_addr,
|
||||
unsigned size)
|
||||
{
|
||||
Genode::Page_slab * slab = Kernel::core_pd()->platform_pd()->_pslab;
|
||||
slab->backing_store(_core_mem_allocator->raw());
|
||||
bool ret = ::unmap_local(virt_addr, size / get_page_size());
|
||||
slab->backing_store(_core_mem_allocator);
|
||||
return ret;
|
||||
}
|
||||
unsigned size) {
|
||||
return ::unmap_local(virt_addr, size / get_page_size()); }
|
||||
|
@ -33,7 +33,7 @@ Core_mem_allocator * Hw::Address_space::_cma() {
|
||||
return static_cast<Core_mem_allocator*>(platform()->core_mem_alloc()); }
|
||||
|
||||
|
||||
void * Hw::Address_space::_tt_alloc()
|
||||
void * Hw::Address_space::_table_alloc()
|
||||
{
|
||||
void * ret;
|
||||
if (!_cma()->alloc_aligned(sizeof(Translation_table), (void**)&ret,
|
||||
@ -50,14 +50,12 @@ bool Hw::Address_space::insert_translation(addr_t virt, addr_t phys,
|
||||
for (;;) {
|
||||
try {
|
||||
Lock::Guard guard(_lock);
|
||||
_tt->insert_translation(virt, phys, size, flags, _pslab);
|
||||
_tt->insert_translation(virt, phys, size, flags, _tt_alloc);
|
||||
return true;
|
||||
} catch(Page_slab::Out_of_slabs) {
|
||||
_pslab->alloc_slab_block();
|
||||
} catch(Allocator::Out_of_memory) {
|
||||
flush(platform()->vm_start(), platform()->vm_size());
|
||||
}
|
||||
}
|
||||
} catch(Allocator::Out_of_memory) {
|
||||
PWRN("Translation table needs to much RAM");
|
||||
} catch(...) {
|
||||
PERR("Invalid mapping %p -> %p (%zx)", (void*)phys, (void*)virt, size);
|
||||
}
|
||||
@ -70,7 +68,7 @@ void Hw::Address_space::flush(addr_t virt, size_t size)
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
try {
|
||||
if (_tt) _tt->remove_translation(virt, size, _pslab);
|
||||
if (_tt) _tt->remove_translation(virt, size, _tt_alloc);
|
||||
|
||||
/* update translation caches */
|
||||
Kernel::update_pd(_kernel_pd);
|
||||
@ -81,25 +79,25 @@ void Hw::Address_space::flush(addr_t virt, size_t size)
|
||||
|
||||
|
||||
Hw::Address_space::Address_space(Kernel::Pd* pd, Translation_table * tt,
|
||||
Page_slab * slab)
|
||||
: _tt(tt), _tt_phys(tt), _pslab(slab), _kernel_pd(pd) { }
|
||||
Translation_table_allocator * tt_alloc)
|
||||
: _tt(tt), _tt_phys(tt), _tt_alloc(tt_alloc), _kernel_pd(pd) { }
|
||||
|
||||
|
||||
Hw::Address_space::Address_space(Kernel::Pd * pd)
|
||||
: _tt(construct_at<Translation_table>(_tt_alloc())),
|
||||
: _tt(construct_at<Translation_table>(_table_alloc())),
|
||||
_tt_phys(reinterpret_cast<Translation_table*>(_cma()->phys_addr(_tt))),
|
||||
_pslab(new (_cma()) Page_slab(_cma())),
|
||||
_tt_alloc((new (_cma()) Table_allocator(_cma()))->alloc()),
|
||||
_kernel_pd(pd)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
Kernel::mtc()->map(_tt, _pslab);
|
||||
Kernel::mtc()->map(_tt, _tt_alloc);
|
||||
}
|
||||
|
||||
|
||||
Hw::Address_space::~Address_space()
|
||||
{
|
||||
flush(platform()->vm_start(), platform()->vm_size());
|
||||
destroy(_cma(), _pslab);
|
||||
destroy(_cma(), Table_allocator::base(_tt_alloc));
|
||||
destroy(_cma(), _tt);
|
||||
}
|
||||
|
||||
@ -151,8 +149,9 @@ int Platform_pd::assign_parent(Native_capability parent)
|
||||
}
|
||||
|
||||
|
||||
Platform_pd::Platform_pd(Translation_table * tt, Page_slab * slab)
|
||||
: Hw::Address_space(kernel_object(), tt, slab),
|
||||
Platform_pd::Platform_pd(Translation_table * tt,
|
||||
Translation_table_allocator * alloc)
|
||||
: Hw::Address_space(kernel_object(), tt, alloc),
|
||||
Kernel_object<Kernel::Pd>(false, tt, this),
|
||||
_label("core") { }
|
||||
|
||||
@ -180,13 +179,19 @@ Translation_table * const Core_platform_pd::_table()
|
||||
}
|
||||
|
||||
|
||||
Page_slab * const Core_platform_pd::_slab()
|
||||
Translation_table_allocator * const Core_platform_pd::_table_alloc()
|
||||
{
|
||||
using Slab = Kernel::Early_translations_slab;
|
||||
using Allocator = Kernel::Early_translations_allocator;
|
||||
|
||||
return unmanaged_singleton<Slab,
|
||||
Slab::ALIGN>(unmanaged_singleton<Allocator>());
|
||||
/**
|
||||
* Core's translation table allocator should contain as much tables
|
||||
* needed to populate the whole virtual memory available to core.
|
||||
* By now, we do not cover the limitation of core's virtula memory
|
||||
* when opening e.g. sessions on behalf of clients. Therefore, for
|
||||
* the time being the number of tables is set to some reasonable
|
||||
* high number.
|
||||
*/
|
||||
using Pa = Translation_table_allocator_tpl<1024>;
|
||||
static Pa * pa = unmanaged_singleton<Pa, Pa::ALIGN>();
|
||||
return pa->alloc();
|
||||
}
|
||||
|
||||
|
||||
@ -199,9 +204,7 @@ void Core_platform_pd::_map(addr_t start, addr_t end, bool io_mem)
|
||||
size_t size = round_page(end) - start;
|
||||
|
||||
try {
|
||||
_table()->insert_translation(start, start, size, flags, _slab());
|
||||
} catch(Page_slab::Out_of_slabs) {
|
||||
PERR("Not enough page slabs");
|
||||
_table()->insert_translation(start, start, size, flags, _table_alloc());
|
||||
} catch(Allocator::Out_of_memory) {
|
||||
PERR("Translation table needs to much RAM");
|
||||
} catch(...) {
|
||||
@ -212,10 +215,10 @@ void Core_platform_pd::_map(addr_t start, addr_t end, bool io_mem)
|
||||
|
||||
|
||||
Core_platform_pd::Core_platform_pd()
|
||||
: Platform_pd(_table(), _slab())
|
||||
: Platform_pd(_table(), _table_alloc())
|
||||
{
|
||||
/* map exception vector for core */
|
||||
Kernel::mtc()->map(_table(), _slab());
|
||||
Kernel::mtc()->map(_table(), _table_alloc());
|
||||
|
||||
/* map core's program image */
|
||||
_map((addr_t)&_prog_img_beg, (addr_t)&_prog_img_end, false);
|
||||
|
@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <platform_thread.h>
|
||||
#include <platform_pd.h>
|
||||
#include <core_env.h>
|
||||
|
@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/kernel.h>
|
||||
#include <kernel/pd.h>
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <util/bit_allocator.h>
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <kernel/pd.h>
|
||||
|
||||
using Asid_allocator = Genode::Bit_allocator<256>;
|
||||
|
@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/kernel.h>
|
||||
|
@ -34,3 +34,14 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint *ds_ep,
|
||||
{
|
||||
_ds.assign_core_local_addr(core_env()->rm_session()->attach(_ds_cap));
|
||||
}
|
||||
|
||||
|
||||
Vm_session_component::~Vm_session_component()
|
||||
{
|
||||
/* dissolve VM dataspace from service entry point */
|
||||
_ds_ep->dissolve(&_ds);
|
||||
|
||||
/* free region in allocator */
|
||||
core_env()->rm_session()->detach(_ds.core_local_addr());
|
||||
platform()->ram_alloc()->free((void*)_ds.phys_addr());
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <platform_pd.h>
|
||||
#include <kernel/vm.h>
|
||||
|
||||
|
@ -39,13 +39,8 @@ void Vm_session_component::_attach(addr_t phys_addr, addr_t vm_addr, size_t size
|
||||
Page_flags pflags = Page_flags::apply_mapping(true, CACHED, false);
|
||||
|
||||
try {
|
||||
for (;;)
|
||||
try {
|
||||
_table->insert_translation(vm_addr, phys_addr, size, pflags, _pslab);
|
||||
return;
|
||||
} catch(Page_slab::Out_of_slabs) {
|
||||
_pslab->alloc_slab_block();
|
||||
}
|
||||
_table->insert_translation(vm_addr, phys_addr, size, pflags, _tt_alloc);
|
||||
return;
|
||||
} catch(Allocator::Out_of_memory) {
|
||||
PERR("Translation table needs to much RAM");
|
||||
} catch(...) {
|
||||
@ -73,7 +68,7 @@ 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, _pslab); }
|
||||
_table->remove_translation(vm_addr, size, _tt_alloc); }
|
||||
|
||||
|
||||
Vm_session_component::Vm_session_component(Rpc_entrypoint *ds_ep,
|
||||
@ -94,6 +89,21 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint *ds_ep,
|
||||
throw Root::Quota_exceeded();
|
||||
}
|
||||
|
||||
_table = construct_at<Translation_table>(tt);
|
||||
_pslab = new (cma) Page_slab(cma);
|
||||
_table = construct_at<Translation_table>(tt);
|
||||
_tt_alloc = (new (cma) Table_allocator(cma))->alloc();
|
||||
}
|
||||
|
||||
|
||||
Vm_session_component::~Vm_session_component()
|
||||
{
|
||||
/* dissolve VM dataspace from service entry point */
|
||||
_ds_ep->dissolve(&_ds);
|
||||
|
||||
/* free region in allocator */
|
||||
core_env()->rm_session()->detach(_ds.core_local_addr());
|
||||
platform()->ram_alloc()->free((void*)_ds.phys_addr());
|
||||
|
||||
/* free guest-to-host page tables */
|
||||
destroy(platform()->core_mem_alloc(), _table);
|
||||
destroy(platform()->core_mem_alloc(), Table_allocator::base(_tt_alloc));
|
||||
}
|
||||
|
@ -42,14 +42,3 @@ void Vm_session_component::pause(void)
|
||||
if (Kernel_object<Kernel::Vm>::_cap.valid())
|
||||
Kernel::pause_vm(kernel_object());
|
||||
}
|
||||
|
||||
|
||||
Vm_session_component::~Vm_session_component()
|
||||
{
|
||||
/* dissolve VM dataspace from service entry point */
|
||||
_ds_ep->dissolve(&_ds);
|
||||
|
||||
/* free region in allocator */
|
||||
core_env()->rm_session()->detach(_ds.core_local_addr());
|
||||
platform()->ram_alloc()->free((void*)_ds.phys_addr());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user