From cc58b119988f44e0dbb59998086e8ba9caccb54e Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Tue, 16 Jun 2015 10:59:26 +0200 Subject: [PATCH] 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 --- .../src/core/include/kernel/configuration.h | 5 +- .../core/include/kernel/early_translations.h | 83 ------- repos/base-hw/src/core/include/kernel/pd.h | 23 +- repos/base-hw/src/core/include/page_slab.h | 230 ------------------ repos/base-hw/src/core/include/platform_pd.h | 44 ++-- .../spec/arm/short_translation_table.h | 31 +-- .../spec/arm_v7/long_translation_table.h | 78 +++--- .../virtualization/vm_session_component.h | 16 +- .../include/spec/x86_64/translation_table.h | 109 +++++---- .../include/translation_table_allocator.h | 161 ++++++++++++ repos/base-hw/src/core/kernel/ipc_node.cc | 1 + repos/base-hw/src/core/kernel/pd.cc | 11 +- repos/base-hw/src/core/kernel/thread.cc | 1 + repos/base-hw/src/core/platform.cc | 27 +- repos/base-hw/src/core/platform_pd.cc | 55 +++-- repos/base-hw/src/core/platform_thread.cc | 1 + repos/base-hw/src/core/spec/arm/kernel/cpu.cc | 1 + repos/base-hw/src/core/spec/arm/kernel/pd.cc | 1 + .../src/core/spec/arm/kernel/thread.cc | 1 + .../arm_v7/trustzone/vm_session_component.cc | 11 + .../spec/arm_v7/virtualization/kernel/vm.cc | 1 + .../virtualization/vm_session_component.cc | 30 ++- .../core/spec/arm_v7/vm_session_component.cc | 11 - 23 files changed, 407 insertions(+), 525 deletions(-) delete mode 100644 repos/base-hw/src/core/include/kernel/early_translations.h delete mode 100644 repos/base-hw/src/core/include/page_slab.h create mode 100644 repos/base-hw/src/core/include/translation_table_allocator.h diff --git a/repos/base-hw/src/core/include/kernel/configuration.h b/repos/base-hw/src/core/include/kernel/configuration.h index a0204c3e85..6903c4f529 100644 --- a/repos/base-hw/src/core/include/kernel/configuration.h +++ b/repos/base-hw/src/core/include/kernel/configuration.h @@ -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; diff --git a/repos/base-hw/src/core/include/kernel/early_translations.h b/repos/base-hw/src/core/include/kernel/early_translations.h deleted file mode 100644 index 2220dea32e..0000000000 --- a/repos/base-hw/src/core/include/kernel/early_translations.h +++ /dev/null @@ -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 -#include -#include - -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_ */ diff --git a/repos/base-hw/src/core/include/kernel/pd.h b/repos/base-hw/src/core/include/kernel/pd.h index 34cbd0a23d..345a02822c 100644 --- a/repos/base-hw/src/core/include/kernel/pd.h +++ b/repos/base-hw/src/core/include/kernel/pd.h @@ -16,12 +16,11 @@ #define _KERNEL__PD_H_ /* core includes */ -#include +#include #include #include 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 diff --git a/repos/base-hw/src/core/include/page_slab.h b/repos/base-hw/src/core/include/page_slab.h deleted file mode 100644 index 05d93ea75f..0000000000 --- a/repos/base-hw/src/core/include/page_slab.h +++ /dev/null @@ -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 -#include -#include -#include -#include - -#include - -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 indices; - List_element 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 > _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 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(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 *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 *le = _b_list.first(); le;) { - List_element *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_ */ diff --git a/repos/base-hw/src/core/include/platform_pd.h b/repos/base-hw/src/core/include/platform_pd.h index 3966a3a1e5..8b5c247bee 100644 --- a/repos/base-hw/src/core/include/platform_pd.h +++ b/repos/base-hw/src/core/include/platform_pd.h @@ -19,13 +19,17 @@ #include #include #include -#include +#include #include +#include #include #include 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; + + 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. diff --git a/repos/base-hw/src/core/include/spec/arm/short_translation_table.h b/repos/base-hw/src/core/include/spec/arm/short_translation_table.h index 7153b00152..526165491d 100644 --- a/repos/base-hw/src/core/include/spec/arm/short_translation_table.h +++ b/repos/base-hw/src/core/include/spec/arm/short_translation_table.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include 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; } diff --git a/repos/base-hw/src/core/include/spec/arm_v7/long_translation_table.h b/repos/base-hw/src/core/include/spec/arm_v7/long_translation_table.h index 20acb5ac5a..6347b238af 100644 --- a/repos/base-hw/src/core/include/spec/arm_v7/long_translation_table.h +++ b/repos/base-hw/src/core/include/spec/arm_v7/long_translation_table.h @@ -21,7 +21,7 @@ /* base-hw includes */ #include -#include +#include 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 { diff --git a/repos/base-hw/src/core/include/spec/arm_v7/virtualization/vm_session_component.h b/repos/base-hw/src/core/include/spec/arm_v7/virtualization/vm_session_component.h index 27a7f85fbf..b5ac486729 100644 --- a/repos/base-hw/src/core/include/spec/arm_v7/virtualization/vm_session_component.h +++ b/repos/base-hw/src/core/include/spec/arm_v7/virtualization/vm_session_component.h @@ -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), diff --git a/repos/base-hw/src/core/include/spec/x86_64/translation_table.h b/repos/base-hw/src/core/include/spec/x86_64/translation_table.h index 496bc32147..3e8a8e9e35 100644 --- a/repos/base-hw/src/core/include/spec/x86_64/translation_table.h +++ b/repos/base-hw/src/core/include/spec/x86_64/translation_table.h @@ -22,7 +22,7 @@ /* base-hw includes */ #include -#include +#include 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))); diff --git a/repos/base-hw/src/core/include/translation_table_allocator.h b/repos/base-hw/src/core/include/translation_table_allocator.h new file mode 100644 index 0000000000..10fc4f6de6 --- /dev/null +++ b/repos/base-hw/src/core/include/translation_table_allocator.h @@ -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 +#include +#include +#include +#include + +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 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 +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 +class Genode::Translation_table_allocator_tpl::Allocator +: public Translation_table_allocator +{ + private: + + Table *_tables; + Bit_allocator _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::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_ */ diff --git a/repos/base-hw/src/core/kernel/ipc_node.cc b/repos/base-hw/src/core/kernel/ipc_node.cc index 665ed6df89..15122bf360 100644 --- a/repos/base-hw/src/core/kernel/ipc_node.cc +++ b/repos/base-hw/src/core/kernel/ipc_node.cc @@ -17,6 +17,7 @@ #include /* core includes */ +#include #include #include #include diff --git a/repos/base-hw/src/core/kernel/pd.cc b/repos/base-hw/src/core/kernel/pd.cc index d47dce6813..c92a92199d 100644 --- a/repos/base-hw/src/core/kernel/pd.cc +++ b/repos/base-hw/src/core/kernel/pd.cc @@ -17,6 +17,8 @@ #include /* Genode includes */ +#include +#include #include 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)); } diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index dbca461f73..7d8bb23eaf 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -19,6 +19,7 @@ #include /* core includes */ +#include #include #include #include diff --git a/repos/base-hw/src/core/platform.cc b/repos/base-hw/src/core/platform.cc index 1c9dad5e63..9a39b39b0c 100644 --- a/repos/base-hw/src/core/platform.cc +++ b/repos/base-hw/src/core/platform.cc @@ -19,10 +19,10 @@ /* core includes */ #include -#include #include #include #include +#include #include #include #include @@ -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()); } diff --git a/repos/base-hw/src/core/platform_pd.cc b/repos/base-hw/src/core/platform_pd.cc index f5360b1a00..aef6c9dac9 100644 --- a/repos/base-hw/src/core/platform_pd.cc +++ b/repos/base-hw/src/core/platform_pd.cc @@ -33,7 +33,7 @@ Core_mem_allocator * Hw::Address_space::_cma() { return static_cast(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(_tt_alloc())), +: _tt(construct_at(_table_alloc())), _tt_phys(reinterpret_cast(_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(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(unmanaged_singleton()); + /** + * 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(); + 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); diff --git a/repos/base-hw/src/core/platform_thread.cc b/repos/base-hw/src/core/platform_thread.cc index 5df7735355..e2c6084276 100644 --- a/repos/base-hw/src/core/platform_thread.cc +++ b/repos/base-hw/src/core/platform_thread.cc @@ -13,6 +13,7 @@ */ /* core includes */ +#include #include #include #include diff --git a/repos/base-hw/src/core/spec/arm/kernel/cpu.cc b/repos/base-hw/src/core/spec/arm/kernel/cpu.cc index 577c5a6732..94ee1f5e9e 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/cpu.cc @@ -13,6 +13,7 @@ */ /* core includes */ +#include #include #include #include diff --git a/repos/base-hw/src/core/spec/arm/kernel/pd.cc b/repos/base-hw/src/core/spec/arm/kernel/pd.cc index 8ef9ff2875..d851ed59ef 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/pd.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/pd.cc @@ -15,6 +15,7 @@ #include /* core includes */ +#include #include using Asid_allocator = Genode::Bit_allocator<256>; diff --git a/repos/base-hw/src/core/spec/arm/kernel/thread.cc b/repos/base-hw/src/core/spec/arm/kernel/thread.cc index ffd45978d3..38ab6dc11c 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/thread.cc @@ -13,6 +13,7 @@ */ /* core includes */ +#include #include #include #include diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc index 7340d39d7d..a4377e4cff 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.cc @@ -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()); +} diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc index d35134d537..356af34bfa 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc @@ -11,6 +11,7 @@ * under the terms of the GNU General Public License version 2. */ +#include #include #include diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc index 3307d4651c..872e499101 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc @@ -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(tt); - _pslab = new (cma) Page_slab(cma); + _table = construct_at(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)); } diff --git a/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc b/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc index 55ee6f1a8f..625eeaa2a8 100644 --- a/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm_v7/vm_session_component.cc @@ -42,14 +42,3 @@ void Vm_session_component::pause(void) if (Kernel_object::_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()); -}