mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 23:12:24 +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
|
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 */
|
/* amount of priority bands amongst quota owners in CPU scheduling */
|
||||||
constexpr unsigned cpu_priorities = 4;
|
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_
|
#define _KERNEL__PD_H_
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <kernel/early_translations.h>
|
#include <translation_table.h>
|
||||||
#include <kernel/cpu.h>
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/object.h>
|
#include <kernel/object.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
class Page_slab;
|
|
||||||
class Platform_pd;
|
class Platform_pd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,13 +55,15 @@ class Kernel::Mode_transition_control
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef Early_translations_allocator Allocator;
|
/*
|
||||||
typedef Early_translations_slab Slab;
|
* 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;
|
typedef Genode::Translation_table Table;
|
||||||
typedef Genode::Page_flags Page_flags;
|
|
||||||
|
|
||||||
Allocator _allocator;
|
Allocator _alloc;
|
||||||
Slab _slab;
|
|
||||||
Table _table;
|
Table _table;
|
||||||
Cpu_context _master;
|
Cpu_context _master;
|
||||||
|
|
||||||
@ -101,10 +102,10 @@ class Kernel::Mode_transition_control
|
|||||||
* Map the mode transition page to a virtual address space
|
* Map the mode transition page to a virtual address space
|
||||||
*
|
*
|
||||||
* \param tt translation buffer of the address space
|
* \param tt translation buffer of the address space
|
||||||
* \param ram RAM donation for mapping (first try without)
|
* \param alloc translation table allocator used for the mapping
|
||||||
*/
|
*/
|
||||||
void map(Genode::Translation_table * tt,
|
void map(Genode::Translation_table * tt,
|
||||||
Genode::Page_slab * alloc);
|
Genode::Translation_table_allocator * alloc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Continue execution of client context
|
* 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 <translation_table.h>
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <address_space.h>
|
#include <address_space.h>
|
||||||
#include <page_slab.h>
|
#include <translation_table_allocator.h>
|
||||||
#include <object.h>
|
#include <object.h>
|
||||||
|
#include <kernel/configuration.h>
|
||||||
#include <kernel/object.h>
|
#include <kernel/object.h>
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
|
|
||||||
namespace Hw
|
namespace Hw
|
||||||
{
|
{
|
||||||
|
using namespace Kernel;
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Memory virtualization interface of a protection domain
|
* 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::Platform;
|
||||||
friend class Genode::Core_mem_allocator::Mapped_mem_allocator;
|
friend class Genode::Core_mem_allocator::Mapped_mem_allocator;
|
||||||
|
|
||||||
|
using Table_allocator =
|
||||||
|
Translation_table_allocator_tpl<DEFAULT_TRANSLATION_TABLE_MAX>;
|
||||||
|
|
||||||
Genode::Lock _lock; /* table lock */
|
Genode::Lock _lock; /* table lock */
|
||||||
Genode::Translation_table * _tt; /* table virtual addr. */
|
Genode::Translation_table * _tt; /* table virt addr */
|
||||||
Genode::Translation_table * _tt_phys; /* table physical addr. */
|
Genode::Translation_table * _tt_phys; /* table phys addr */
|
||||||
Genode::Page_slab * _pslab; /* page table allocator */
|
Genode::Translation_table_allocator * _tt_alloc; /* table allocator */
|
||||||
Kernel::Pd * _kernel_pd;
|
Kernel::Pd * _kernel_pd;
|
||||||
|
|
||||||
static inline Genode::Core_mem_allocator * _cma();
|
static inline Genode::Core_mem_allocator * _cma();
|
||||||
static inline void * _tt_alloc();
|
static inline void * _table_alloc();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -74,11 +81,11 @@ class Hw::Address_space : public Genode::Address_space
|
|||||||
*
|
*
|
||||||
* \param pd pointer to kernel's pd object
|
* \param pd pointer to kernel's pd object
|
||||||
* \param tt pointer to translation table
|
* \param tt pointer to translation table
|
||||||
* \param slab pointer to page slab allocator
|
* \param tt_alloc pointer to translation table allocator
|
||||||
*/
|
*/
|
||||||
Address_space(Kernel::Pd * pd,
|
Address_space(Kernel::Pd * pd,
|
||||||
Genode::Translation_table * tt,
|
Genode::Translation_table * tt,
|
||||||
Genode::Page_slab * slab);
|
Genode::Translation_table_allocator * tt_alloc);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -159,9 +166,10 @@ class Genode::Platform_pd : public Hw::Address_space,
|
|||||||
* Constructor for core pd
|
* Constructor for core pd
|
||||||
*
|
*
|
||||||
* \param tt translation table address
|
* \param tt translation table address
|
||||||
* \param slab page table allocator
|
* \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:
|
public:
|
||||||
|
|
||||||
@ -206,7 +214,7 @@ class Genode::Core_platform_pd : public Genode::Platform_pd
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
static inline Translation_table * const _table();
|
static inline Translation_table * const _table();
|
||||||
static inline Page_slab * const _slab();
|
static inline Translation_table_allocator * const _table_alloc();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Establish initial one-to-one mappings for core/kernel.
|
* Establish initial one-to-one mappings for core/kernel.
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include <util.h>
|
#include <util.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <page_flags.h>
|
#include <page_flags.h>
|
||||||
#include <page_slab.h>
|
#include <translation_table_allocator.h>
|
||||||
#include <cpu.h>
|
#include <cpu.h>
|
||||||
|
|
||||||
namespace Genode
|
namespace Genode
|
||||||
@ -412,22 +412,22 @@ class Genode::Translation_table
|
|||||||
* \param pa physical start address of range
|
* \param pa physical start address of range
|
||||||
* \param size size of range
|
* \param size size of range
|
||||||
* \param flags mapping flags
|
* \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,
|
void _insert_second_level(unsigned i, addr_t const vo, addr_t const pa,
|
||||||
size_t const size, Page_flags const & flags,
|
size_t const size, Page_flags const & flags,
|
||||||
Page_slab * const slab)
|
Translation_table_allocator * const alloc)
|
||||||
{
|
{
|
||||||
Page_table * pt = 0;
|
Page_table * pt = 0;
|
||||||
switch (Descriptor::type(_entries[i])) {
|
switch (Descriptor::type(_entries[i])) {
|
||||||
|
|
||||||
case Descriptor::FAULT:
|
case Descriptor::FAULT:
|
||||||
{
|
{
|
||||||
if (!slab) throw Allocator::Out_of_memory();
|
if (!alloc) throw Allocator::Out_of_memory();
|
||||||
|
|
||||||
/* create and link page table */
|
/* create and link page table */
|
||||||
pt = new (slab) Page_table();
|
pt = new (alloc) Page_table();
|
||||||
Page_table * pt_phys = (Page_table*) slab->phys_addr(pt);
|
Page_table * pt_phys = (Page_table*) alloc->phys_addr(pt);
|
||||||
pt_phys = pt_phys ? pt_phys : pt; /* hack for core */
|
pt_phys = pt_phys ? pt_phys : pt; /* hack for core */
|
||||||
_entries[i] = Page_table_descriptor::create(pt_phys);
|
_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 */
|
/* use allocator to retrieve virtual addr. of page table */
|
||||||
void * pt_phys = (void*)
|
void * pt_phys = (void*)
|
||||||
Page_table_descriptor::Pa::masked(_entries[i]);
|
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 */
|
pt = pt ? pt : (Page_table *)pt_phys ; /* hack for core */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -481,10 +481,11 @@ class Genode::Translation_table
|
|||||||
* \param pa base of physical backing store
|
* \param pa base of physical backing store
|
||||||
* \param size size of translated region
|
* \param size size of translated region
|
||||||
* \param f mapping flags
|
* \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,
|
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 */
|
/* check sanity */
|
||||||
assert(!(vo & Page_table::Descriptor::VIRT_OFFSET_MASK) &&
|
assert(!(vo & Page_table::Descriptor::VIRT_OFFSET_MASK) &&
|
||||||
@ -515,7 +516,8 @@ class Genode::Translation_table
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
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 */
|
/* check whether we wrap */
|
||||||
@ -533,9 +535,10 @@ class Genode::Translation_table
|
|||||||
*
|
*
|
||||||
* \param vo region offset within the tables virtual region
|
* \param vo region offset within the tables virtual region
|
||||||
* \param size region size
|
* \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 */
|
/* check sanity */
|
||||||
assert(vo <= (vo + size));
|
assert(vo <= (vo + size));
|
||||||
@ -553,7 +556,7 @@ class Genode::Translation_table
|
|||||||
typedef Page_table Pt;
|
typedef Page_table Pt;
|
||||||
|
|
||||||
Pt * pt_phys = (Pt *) Ptd::Pa::masked(_entries[i]);
|
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
|
pt = pt ? pt : pt_phys; // TODO hack for core
|
||||||
|
|
||||||
addr_t const pt_vo = vo - Section::Pa::masked(vo);
|
addr_t const pt_vo = vo - Section::Pa::masked(vo);
|
||||||
@ -561,7 +564,7 @@ class Genode::Translation_table
|
|||||||
|
|
||||||
if (pt->empty()) {
|
if (pt->empty()) {
|
||||||
Descriptor::invalidate(_entries[i]);
|
Descriptor::invalidate(_entries[i]);
|
||||||
destroy(slab, pt);
|
destroy(alloc, pt);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
/* base-hw includes */
|
/* base-hw includes */
|
||||||
#include <page_flags.h>
|
#include <page_flags.h>
|
||||||
#include <page_slab.h>
|
#include <translation_table_allocator.h>
|
||||||
|
|
||||||
namespace Genode
|
namespace Genode
|
||||||
{
|
{
|
||||||
@ -325,10 +325,11 @@ class Genode::Level_3_translation_table :
|
|||||||
struct Insert_func
|
struct Insert_func
|
||||||
{
|
{
|
||||||
Page_flags const & flags;
|
Page_flags const & flags;
|
||||||
Page_slab * slab;
|
Translation_table_allocator * alloc;
|
||||||
|
|
||||||
Insert_func(Page_flags const & flags,
|
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,
|
void operator () (addr_t const vo,
|
||||||
addr_t const pa,
|
addr_t const pa,
|
||||||
@ -354,9 +355,9 @@ class Genode::Level_3_translation_table :
|
|||||||
|
|
||||||
struct Remove_func
|
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,
|
void operator () (addr_t const vo,
|
||||||
addr_t const pa,
|
addr_t const pa,
|
||||||
@ -371,11 +372,12 @@ class Genode::Level_3_translation_table :
|
|||||||
addr_t pa,
|
addr_t pa,
|
||||||
size_t size,
|
size_t size,
|
||||||
Page_flags const & flags,
|
Page_flags const & flags,
|
||||||
Page_slab * slab) {
|
Translation_table_allocator * alloc) {
|
||||||
_range_op(vo, pa, size, Insert_func(flags, slab)); }
|
_range_op(vo, pa, size, Insert_func(flags, alloc)); }
|
||||||
|
|
||||||
void remove_translation(addr_t vo, size_t size, Page_slab * slab) {
|
void remove_translation(addr_t vo, size_t size,
|
||||||
_range_op(vo, 0, size, Remove_func(slab)); }
|
Translation_table_allocator * alloc) {
|
||||||
|
_range_op(vo, 0, size, Remove_func(alloc)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -393,10 +395,11 @@ class Genode::Level_x_translation_table :
|
|||||||
struct Insert_func
|
struct Insert_func
|
||||||
{
|
{
|
||||||
Page_flags const & flags;
|
Page_flags const & flags;
|
||||||
Page_slab * slab;
|
Translation_table_allocator * alloc;
|
||||||
|
|
||||||
Insert_func(Page_flags const & flags,
|
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,
|
void operator () (addr_t const vo,
|
||||||
addr_t const pa,
|
addr_t const pa,
|
||||||
@ -420,11 +423,11 @@ class Genode::Level_x_translation_table :
|
|||||||
|
|
||||||
case Descriptor::INVALID: /* no entry */
|
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 */
|
/* create and link next level table */
|
||||||
table = new (slab) ENTRY();
|
table = new (alloc) ENTRY();
|
||||||
ENTRY * phys_addr = (ENTRY*) slab->phys_addr(table);
|
ENTRY * phys_addr = (ENTRY*) alloc->phys_addr(table);
|
||||||
desc = Table_descriptor::create(phys_addr ?
|
desc = Table_descriptor::create(phys_addr ?
|
||||||
phys_addr : table);
|
phys_addr : table);
|
||||||
}
|
}
|
||||||
@ -434,7 +437,7 @@ class Genode::Level_x_translation_table :
|
|||||||
/* use allocator to retrieve virt address of table */
|
/* use allocator to retrieve virt address of table */
|
||||||
ENTRY * phys_addr = (ENTRY*)
|
ENTRY * phys_addr = (ENTRY*)
|
||||||
Table_descriptor::Next_table::masked(desc);
|
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;
|
table = table ? table : (ENTRY*)phys_addr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -447,16 +450,16 @@ class Genode::Level_x_translation_table :
|
|||||||
|
|
||||||
/* insert translation */
|
/* insert translation */
|
||||||
table->insert_translation(vo - (vo & Base::BLOCK_MASK),
|
table->insert_translation(vo - (vo & Base::BLOCK_MASK),
|
||||||
pa, size, flags, slab);
|
pa, size, flags, alloc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Remove_func
|
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,
|
void operator () (addr_t const vo,
|
||||||
addr_t const pa,
|
addr_t const pa,
|
||||||
@ -469,13 +472,13 @@ class Genode::Level_x_translation_table :
|
|||||||
/* use allocator to retrieve virt address of table */
|
/* use allocator to retrieve virt address of table */
|
||||||
ENTRY * phys_addr = (ENTRY*)
|
ENTRY * phys_addr = (ENTRY*)
|
||||||
Table_descriptor::Next_table::masked(desc);
|
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 = table ? table : (ENTRY*)phys_addr;
|
||||||
table->remove_translation(vo - (vo & Base::BLOCK_MASK),
|
table->remove_translation(vo - (vo & Base::BLOCK_MASK),
|
||||||
size, slab);
|
size, alloc);
|
||||||
if (!table->empty())
|
if (!table->empty())
|
||||||
break;
|
break;
|
||||||
destroy(slab, table);
|
destroy(alloc, table);
|
||||||
}
|
}
|
||||||
case Descriptor::BLOCK:
|
case Descriptor::BLOCK:
|
||||||
case Descriptor::INVALID:
|
case Descriptor::INVALID:
|
||||||
@ -498,24 +501,25 @@ class Genode::Level_x_translation_table :
|
|||||||
* \param pa base of the physical backing store
|
* \param pa base of the physical backing store
|
||||||
* \param size size of the translated region
|
* \param size size of the translated region
|
||||||
* \param flags mapping flags
|
* \param flags mapping flags
|
||||||
* \param slab second level page slab allocator
|
* \param alloc second level translation table allocator
|
||||||
*/
|
*/
|
||||||
void insert_translation(addr_t vo,
|
void insert_translation(addr_t vo,
|
||||||
addr_t pa,
|
addr_t pa,
|
||||||
size_t size,
|
size_t size,
|
||||||
Page_flags const & flags,
|
Page_flags const & flags,
|
||||||
Page_slab * slab) {
|
Translation_table_allocator * alloc) {
|
||||||
this->_range_op(vo, pa, size, Insert_func(flags, slab)); }
|
this->_range_op(vo, pa, size, Insert_func(flags, alloc)); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove translations that overlap with a given virtual region
|
* Remove translations that overlap with a given virtual region
|
||||||
*
|
*
|
||||||
* \param vo region offset within the tables virtual region
|
* \param vo region offset within the tables virtual region
|
||||||
* \param size region size
|
* \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,
|
||||||
this->_range_op(vo, 0, size, Remove_func(slab)); }
|
Translation_table_allocator * alloc) {
|
||||||
|
this->_range_op(vo, 0, size, Remove_func(alloc)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
@ -38,6 +38,8 @@ class Genode::Vm_session_component
|
|||||||
|
|
||||||
using Translation_table =
|
using Translation_table =
|
||||||
Genode::Level_1_stage_2_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;
|
Rpc_entrypoint *_ds_ep;
|
||||||
Range_allocator *_ram_alloc;
|
Range_allocator *_ram_alloc;
|
||||||
@ -45,7 +47,7 @@ class Genode::Vm_session_component
|
|||||||
Dataspace_capability _ds_cap;
|
Dataspace_capability _ds_cap;
|
||||||
addr_t _ds_addr;
|
addr_t _ds_addr;
|
||||||
Translation_table *_table;
|
Translation_table *_table;
|
||||||
Page_slab *_pslab;
|
Translation_table_allocator *_tt_alloc;
|
||||||
|
|
||||||
static size_t _ds_size() {
|
static size_t _ds_size() {
|
||||||
return align_addr(sizeof(Cpu_state_modes),
|
return align_addr(sizeof(Cpu_state_modes),
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
/* base-hw includes */
|
/* base-hw includes */
|
||||||
#include <page_flags.h>
|
#include <page_flags.h>
|
||||||
#include <page_slab.h>
|
#include <translation_table_allocator.h>
|
||||||
|
|
||||||
namespace Genode
|
namespace Genode
|
||||||
{
|
{
|
||||||
@ -153,10 +153,11 @@ class Genode::Level_4_translation_table
|
|||||||
struct Insert_func
|
struct Insert_func
|
||||||
{
|
{
|
||||||
Page_flags const & flags;
|
Page_flags const & flags;
|
||||||
Page_slab * slab;
|
Translation_table_allocator * alloc;
|
||||||
|
|
||||||
Insert_func(Page_flags const & flags,
|
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,
|
void operator () (addr_t const vo, addr_t const pa,
|
||||||
size_t const size,
|
size_t const size,
|
||||||
@ -181,9 +182,9 @@ class Genode::Level_4_translation_table
|
|||||||
|
|
||||||
struct Remove_func
|
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,
|
void operator () (addr_t const vo, addr_t const pa,
|
||||||
size_t const size,
|
size_t const size,
|
||||||
@ -247,12 +248,13 @@ class Genode::Level_4_translation_table
|
|||||||
* \param pa base of the physical backing store
|
* \param pa base of the physical backing store
|
||||||
* \param size size of the translated region
|
* \param size size of the translated region
|
||||||
* \param flags mapping flags
|
* \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,
|
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 vo region offset within the tables virtual region
|
||||||
* \param size region size
|
* \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)));
|
} __attribute__((aligned(1 << ALIGNM_LOG2)));
|
||||||
|
|
||||||
@ -356,10 +359,11 @@ class Genode::Page_directory
|
|||||||
struct Insert_func
|
struct Insert_func
|
||||||
{
|
{
|
||||||
Page_flags const & flags;
|
Page_flags const & flags;
|
||||||
Page_slab * slab;
|
Translation_table_allocator * alloc;
|
||||||
|
|
||||||
Insert_func(Page_flags const & flags,
|
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,
|
void operator () (addr_t const vo, addr_t const pa,
|
||||||
size_t const size,
|
size_t const size,
|
||||||
@ -385,12 +389,12 @@ class Genode::Page_directory
|
|||||||
/* we need to use a next level table */
|
/* we need to use a next level table */
|
||||||
ENTRY *table;
|
ENTRY *table;
|
||||||
if (!Base_descriptor::present(desc)) {
|
if (!Base_descriptor::present(desc)) {
|
||||||
if (!slab)
|
if (!alloc)
|
||||||
throw Allocator::Out_of_memory();
|
throw Allocator::Out_of_memory();
|
||||||
|
|
||||||
/* create and link next level table */
|
/* create and link next level table */
|
||||||
table = new (slab) ENTRY();
|
table = new (alloc) ENTRY();
|
||||||
ENTRY * phys_addr = (ENTRY*) slab->phys_addr(table);
|
ENTRY * phys_addr = (ENTRY*) alloc->phys_addr(table);
|
||||||
addr_t const pa = (addr_t)(phys_addr ? phys_addr : table);
|
addr_t const pa = (addr_t)(phys_addr ? phys_addr : table);
|
||||||
desc = (typename Base_descriptor::access_t)
|
desc = (typename Base_descriptor::access_t)
|
||||||
Table_descriptor::create(flags, pa);
|
Table_descriptor::create(flags, pa);
|
||||||
@ -401,21 +405,21 @@ class Genode::Page_directory
|
|||||||
Base_descriptor::merge_access_rights(desc, flags);
|
Base_descriptor::merge_access_rights(desc, flags);
|
||||||
ENTRY * phys_addr = (ENTRY*)
|
ENTRY * phys_addr = (ENTRY*)
|
||||||
Table_descriptor::Pa::masked(desc);
|
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;
|
table = table ? table : (ENTRY*)phys_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* insert translation */
|
/* insert translation */
|
||||||
table->insert_translation(vo - (vo & PAGE_MASK),
|
table->insert_translation(vo - (vo & PAGE_MASK),
|
||||||
pa, size, flags, slab);
|
pa, size, flags, alloc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Remove_func
|
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,
|
void operator () (addr_t const vo, addr_t const pa,
|
||||||
size_t const size,
|
size_t const size,
|
||||||
@ -428,12 +432,12 @@ class Genode::Page_directory
|
|||||||
/* use allocator to retrieve virt address of table */
|
/* use allocator to retrieve virt address of table */
|
||||||
ENTRY* phys_addr = (ENTRY*)
|
ENTRY* phys_addr = (ENTRY*)
|
||||||
Table_descriptor::Pa::masked(desc);
|
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;
|
table = table ? table : (ENTRY*)phys_addr;
|
||||||
addr_t const table_vo = vo - (vo & PAGE_MASK);
|
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()) {
|
if (table->empty()) {
|
||||||
destroy(slab, table);
|
destroy(alloc, table);
|
||||||
desc = 0;
|
desc = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -494,12 +498,13 @@ class Genode::Page_directory
|
|||||||
* \param pa base of the physical backing store
|
* \param pa base of the physical backing store
|
||||||
* \param size size of the translated region
|
* \param size size of the translated region
|
||||||
* \param flags mapping flags
|
* \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,
|
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 vo region offset within the tables virtual region
|
||||||
* \param size region size
|
* \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)));
|
} __attribute__((aligned(1 << ALIGNM_LOG2)));
|
||||||
|
|
||||||
@ -548,10 +554,11 @@ class Genode::Pml4_table
|
|||||||
struct Insert_func
|
struct Insert_func
|
||||||
{
|
{
|
||||||
Page_flags const & flags;
|
Page_flags const & flags;
|
||||||
Page_slab * slab;
|
Translation_table_allocator * alloc;
|
||||||
|
|
||||||
Insert_func(Page_flags const & flags,
|
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,
|
void operator () (addr_t const vo, addr_t const pa,
|
||||||
size_t const size,
|
size_t const size,
|
||||||
@ -560,33 +567,33 @@ class Genode::Pml4_table
|
|||||||
/* we need to use a next level table */
|
/* we need to use a next level table */
|
||||||
ENTRY *table;
|
ENTRY *table;
|
||||||
if (!Descriptor::present(desc)) {
|
if (!Descriptor::present(desc)) {
|
||||||
if (!slab)
|
if (!alloc)
|
||||||
throw Allocator::Out_of_memory();
|
throw Allocator::Out_of_memory();
|
||||||
|
|
||||||
/* create and link next level table */
|
/* create and link next level table */
|
||||||
table = new (slab) ENTRY();
|
table = new (alloc) ENTRY();
|
||||||
ENTRY * phys_addr = (ENTRY*) slab->phys_addr(table);
|
ENTRY * phys_addr = (ENTRY*) alloc->phys_addr(table);
|
||||||
addr_t const pa = (addr_t)(phys_addr ? phys_addr : table);
|
addr_t const pa = (addr_t)(phys_addr ? phys_addr : table);
|
||||||
desc = Descriptor::create(flags, pa);
|
desc = Descriptor::create(flags, pa);
|
||||||
} else {
|
} else {
|
||||||
Descriptor::merge_access_rights(desc, flags);
|
Descriptor::merge_access_rights(desc, flags);
|
||||||
ENTRY * phys_addr = (ENTRY*)
|
ENTRY * phys_addr = (ENTRY*)
|
||||||
Descriptor::Pa::masked(desc);
|
Descriptor::Pa::masked(desc);
|
||||||
table = (ENTRY*) slab->virt_addr(phys_addr);
|
table = (ENTRY*) alloc->virt_addr(phys_addr);
|
||||||
table = table ? table : (ENTRY*)phys_addr;
|
table = table ? table : (ENTRY*)phys_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* insert translation */
|
/* insert translation */
|
||||||
addr_t const table_vo = vo - (vo & PAGE_MASK);
|
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
|
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,
|
void operator () (addr_t const vo, addr_t const pa,
|
||||||
size_t const size,
|
size_t const size,
|
||||||
@ -596,12 +603,12 @@ class Genode::Pml4_table
|
|||||||
/* use allocator to retrieve virt address of table */
|
/* use allocator to retrieve virt address of table */
|
||||||
ENTRY* phys_addr = (ENTRY*)
|
ENTRY* phys_addr = (ENTRY*)
|
||||||
Descriptor::Pa::masked(desc);
|
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;
|
table = table ? table : (ENTRY*)phys_addr;
|
||||||
addr_t const table_vo = vo - (vo & PAGE_MASK);
|
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()) {
|
if (table->empty()) {
|
||||||
destroy(slab, table);
|
destroy(alloc, table);
|
||||||
desc = 0;
|
desc = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -660,12 +667,13 @@ class Genode::Pml4_table
|
|||||||
* \param pa base of the physical backing store
|
* \param pa base of the physical backing store
|
||||||
* \param size size of the translated region
|
* \param size size of the translated region
|
||||||
* \param flags mapping flags
|
* \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,
|
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 vo region offset within the tables virtual region
|
||||||
* \param size region size
|
* \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)));
|
} __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>
|
#include <base/native_types.h>
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <assert.h>
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
#include <kernel/ipc_node.h>
|
#include <kernel/ipc_node.h>
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
|
#include <assert.h>
|
||||||
|
#include <page_flags.h>
|
||||||
#include <unmanaged_singleton.h>
|
#include <unmanaged_singleton.h>
|
||||||
|
|
||||||
using namespace Kernel;
|
using namespace Kernel;
|
||||||
@ -51,12 +53,12 @@ addr_t Mode_transition_control::_virt_user_entry()
|
|||||||
|
|
||||||
|
|
||||||
void Mode_transition_control::map(Genode::Translation_table * tt,
|
void Mode_transition_control::map(Genode::Translation_table * tt,
|
||||||
Genode::Page_slab * alloc)
|
Genode::Translation_table_allocator * alloc)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
addr_t const phys_base = (addr_t)&_mt_begin;
|
addr_t const phys_base = (addr_t)&_mt_begin;
|
||||||
tt->insert_translation(VIRT_BASE, phys_base, SIZE,
|
tt->insert_translation(VIRT_BASE, phys_base, SIZE,
|
||||||
Page_flags::mode_transition(), alloc);
|
Genode::Page_flags::mode_transition(), alloc);
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
PERR("Inserting exception vector in page table failed!"); }
|
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()
|
Mode_transition_control::Mode_transition_control() : _master(&_table)
|
||||||
: _slab(&_allocator), _master(&_table)
|
|
||||||
{
|
{
|
||||||
assert(Genode::aligned(this, ALIGN_LOG2));
|
assert(Genode::aligned(this, ALIGN_LOG2));
|
||||||
assert(sizeof(_master) <= _master_context_size());
|
assert(sizeof(_master) <= _master_context_size());
|
||||||
assert(_size() <= SIZE);
|
assert(_size() <= SIZE);
|
||||||
map(&_table, &_slab);
|
map(&_table, _alloc.alloc());
|
||||||
Genode::memcpy(&_mt_master_context_begin, &_master, sizeof(_master));
|
Genode::memcpy(&_mt_master_context_begin, &_master, sizeof(_master));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <util/construct_at.h>
|
#include <util/construct_at.h>
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <assert.h>
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
#include <kernel/thread.h>
|
#include <kernel/thread.h>
|
||||||
#include <kernel/irq.h>
|
#include <kernel/irq.h>
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <core_parent.h>
|
#include <core_parent.h>
|
||||||
#include <page_slab.h>
|
|
||||||
#include <map_local.h>
|
#include <map_local.h>
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
|
#include <page_flags.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
#include <pic.h>
|
#include <pic.h>
|
||||||
#include <kernel/kernel.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 };
|
static Native_region r = { VIRT_ADDR_SPACE_START, VIRT_ADDR_SPACE_SIZE };
|
||||||
return i ? 0 : &r; }
|
return i ? 0 : &r; }
|
||||||
|
|
||||||
static Core_mem_allocator * _core_mem_allocator = 0;
|
|
||||||
|
|
||||||
Platform::Platform()
|
Platform::Platform()
|
||||||
:
|
:
|
||||||
@ -115,10 +114,6 @@ Platform::Platform()
|
|||||||
_irq_alloc(core_mem_alloc()),
|
_irq_alloc(core_mem_alloc()),
|
||||||
_vm_start(VIRT_ADDR_SPACE_START), _vm_size(VIRT_ADDR_SPACE_SIZE)
|
_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.
|
* Initialise platform resource allocators.
|
||||||
* Core mem alloc must come first because it is
|
* 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,
|
bool Core_mem_allocator::Mapped_mem_allocator::_map_local(addr_t virt_addr,
|
||||||
addr_t phys_addr,
|
addr_t phys_addr,
|
||||||
unsigned size)
|
unsigned size) {
|
||||||
{
|
return ::map_local(phys_addr, virt_addr, size / get_page_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Core_mem_allocator::Mapped_mem_allocator::_unmap_local(addr_t virt_addr,
|
bool Core_mem_allocator::Mapped_mem_allocator::_unmap_local(addr_t virt_addr,
|
||||||
unsigned size)
|
unsigned size) {
|
||||||
{
|
return ::unmap_local(virt_addr, size / get_page_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;
|
|
||||||
}
|
|
||||||
|
@ -33,7 +33,7 @@ Core_mem_allocator * Hw::Address_space::_cma() {
|
|||||||
return static_cast<Core_mem_allocator*>(platform()->core_mem_alloc()); }
|
return static_cast<Core_mem_allocator*>(platform()->core_mem_alloc()); }
|
||||||
|
|
||||||
|
|
||||||
void * Hw::Address_space::_tt_alloc()
|
void * Hw::Address_space::_table_alloc()
|
||||||
{
|
{
|
||||||
void * ret;
|
void * ret;
|
||||||
if (!_cma()->alloc_aligned(sizeof(Translation_table), (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 (;;) {
|
for (;;) {
|
||||||
try {
|
try {
|
||||||
Lock::Guard guard(_lock);
|
Lock::Guard guard(_lock);
|
||||||
_tt->insert_translation(virt, phys, size, flags, _pslab);
|
_tt->insert_translation(virt, phys, size, flags, _tt_alloc);
|
||||||
return true;
|
return true;
|
||||||
} catch(Page_slab::Out_of_slabs) {
|
|
||||||
_pslab->alloc_slab_block();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(Allocator::Out_of_memory) {
|
} catch(Allocator::Out_of_memory) {
|
||||||
PWRN("Translation table needs to much RAM");
|
flush(platform()->vm_start(), platform()->vm_size());
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
PERR("Invalid mapping %p -> %p (%zx)", (void*)phys, (void*)virt, size);
|
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);
|
Lock::Guard guard(_lock);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (_tt) _tt->remove_translation(virt, size, _pslab);
|
if (_tt) _tt->remove_translation(virt, size, _tt_alloc);
|
||||||
|
|
||||||
/* update translation caches */
|
/* update translation caches */
|
||||||
Kernel::update_pd(_kernel_pd);
|
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,
|
Hw::Address_space::Address_space(Kernel::Pd* pd, Translation_table * tt,
|
||||||
Page_slab * slab)
|
Translation_table_allocator * tt_alloc)
|
||||||
: _tt(tt), _tt_phys(tt), _pslab(slab), _kernel_pd(pd) { }
|
: _tt(tt), _tt_phys(tt), _tt_alloc(tt_alloc), _kernel_pd(pd) { }
|
||||||
|
|
||||||
|
|
||||||
Hw::Address_space::Address_space(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))),
|
_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)
|
_kernel_pd(pd)
|
||||||
{
|
{
|
||||||
Lock::Guard guard(_lock);
|
Lock::Guard guard(_lock);
|
||||||
Kernel::mtc()->map(_tt, _pslab);
|
Kernel::mtc()->map(_tt, _tt_alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Hw::Address_space::~Address_space()
|
Hw::Address_space::~Address_space()
|
||||||
{
|
{
|
||||||
flush(platform()->vm_start(), platform()->vm_size());
|
flush(platform()->vm_start(), platform()->vm_size());
|
||||||
destroy(_cma(), _pslab);
|
destroy(_cma(), Table_allocator::base(_tt_alloc));
|
||||||
destroy(_cma(), _tt);
|
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)
|
Platform_pd::Platform_pd(Translation_table * tt,
|
||||||
: Hw::Address_space(kernel_object(), tt, slab),
|
Translation_table_allocator * alloc)
|
||||||
|
: Hw::Address_space(kernel_object(), tt, alloc),
|
||||||
Kernel_object<Kernel::Pd>(false, tt, this),
|
Kernel_object<Kernel::Pd>(false, tt, this),
|
||||||
_label("core") { }
|
_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;
|
* Core's translation table allocator should contain as much tables
|
||||||
|
* needed to populate the whole virtual memory available to core.
|
||||||
return unmanaged_singleton<Slab,
|
* By now, we do not cover the limitation of core's virtula memory
|
||||||
Slab::ALIGN>(unmanaged_singleton<Allocator>());
|
* 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;
|
size_t size = round_page(end) - start;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_table()->insert_translation(start, start, size, flags, _slab());
|
_table()->insert_translation(start, start, size, flags, _table_alloc());
|
||||||
} catch(Page_slab::Out_of_slabs) {
|
|
||||||
PERR("Not enough page slabs");
|
|
||||||
} catch(Allocator::Out_of_memory) {
|
} catch(Allocator::Out_of_memory) {
|
||||||
PERR("Translation table needs to much RAM");
|
PERR("Translation table needs to much RAM");
|
||||||
} catch(...) {
|
} 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()
|
Core_platform_pd::Core_platform_pd()
|
||||||
: Platform_pd(_table(), _slab())
|
: Platform_pd(_table(), _table_alloc())
|
||||||
{
|
{
|
||||||
/* map exception vector for core */
|
/* map exception vector for core */
|
||||||
Kernel::mtc()->map(_table(), _slab());
|
Kernel::mtc()->map(_table(), _table_alloc());
|
||||||
|
|
||||||
/* map core's program image */
|
/* map core's program image */
|
||||||
_map((addr_t)&_prog_img_beg, (addr_t)&_prog_img_end, false);
|
_map((addr_t)&_prog_img_beg, (addr_t)&_prog_img_end, false);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <assert.h>
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
#include <core_env.h>
|
#include <core_env.h>
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <assert.h>
|
||||||
#include <kernel/cpu.h>
|
#include <kernel/cpu.h>
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <util/bit_allocator.h>
|
#include <util/bit_allocator.h>
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <assert.h>
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
|
|
||||||
using Asid_allocator = Genode::Bit_allocator<256>;
|
using Asid_allocator = Genode::Bit_allocator<256>;
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <assert.h>
|
||||||
#include <kernel/thread.h>
|
#include <kernel/thread.h>
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
#include <kernel/kernel.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));
|
_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.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
#include <kernel/vm.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);
|
Page_flags pflags = Page_flags::apply_mapping(true, CACHED, false);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (;;)
|
_table->insert_translation(vm_addr, phys_addr, size, pflags, _tt_alloc);
|
||||||
try {
|
|
||||||
_table->insert_translation(vm_addr, phys_addr, size, pflags, _pslab);
|
|
||||||
return;
|
return;
|
||||||
} catch(Page_slab::Out_of_slabs) {
|
|
||||||
_pslab->alloc_slab_block();
|
|
||||||
}
|
|
||||||
} catch(Allocator::Out_of_memory) {
|
} catch(Allocator::Out_of_memory) {
|
||||||
PERR("Translation table needs to much RAM");
|
PERR("Translation table needs to much RAM");
|
||||||
} catch(...) {
|
} 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) {
|
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,
|
Vm_session_component::Vm_session_component(Rpc_entrypoint *ds_ep,
|
||||||
@ -95,5 +90,20 @@ Vm_session_component::Vm_session_component(Rpc_entrypoint *ds_ep,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_table = construct_at<Translation_table>(tt);
|
_table = construct_at<Translation_table>(tt);
|
||||||
_pslab = new (cma) Page_slab(cma);
|
_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())
|
if (Kernel_object<Kernel::Vm>::_cap.valid())
|
||||||
Kernel::pause_vm(kernel_object());
|
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