mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
hw: allocate core's page-tables outside of binary
Moreover, be strict when calculating the page-table requirements of core, which is architecture specific, and declare the virtual memory requirements of core architecture-wise. Ref #1588
This commit is contained in:
parent
3ee2997198
commit
8abd70e6e7
@ -16,7 +16,7 @@
|
||||
#define _KERNEL__PD_H_
|
||||
|
||||
/* core includes */
|
||||
#include <translation_table.h>
|
||||
#include <translation_table_allocator_tpl.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <kernel/object.h>
|
||||
|
||||
|
@ -22,9 +22,11 @@
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/log.h>
|
||||
#include <kernel/configuration.h>
|
||||
#include <kernel/core_interface.h>
|
||||
|
||||
/* core includes */
|
||||
#include <translation_table_allocator_tpl.h>
|
||||
#include <platform_generic.h>
|
||||
#include <core_rm_session.h>
|
||||
#include <core_mem_alloc.h>
|
||||
@ -121,6 +123,20 @@ namespace Genode {
|
||||
static void setup_irq_mode(unsigned irq_number, unsigned trigger,
|
||||
unsigned polarity);
|
||||
|
||||
/**
|
||||
* Return address of cores translation table allocator
|
||||
*/
|
||||
static addr_t core_translation_tables();
|
||||
|
||||
/**
|
||||
* Return size of cores translation table allocator
|
||||
*/
|
||||
static constexpr size_t core_translation_tables_size()
|
||||
{
|
||||
return round_page(sizeof(Translation_table_allocator_tpl<
|
||||
Translation_table::CORE_TRANS_TABLE_COUNT>));
|
||||
}
|
||||
|
||||
/********************************
|
||||
** Platform_generic interface **
|
||||
********************************/
|
||||
|
@ -279,11 +279,15 @@ class Genode::Translation_table
|
||||
public:
|
||||
|
||||
enum {
|
||||
SIZE_LOG2 = 14,
|
||||
SIZE = 1 << SIZE_LOG2,
|
||||
ALIGNM_LOG2 = SIZE_LOG2,
|
||||
MAX_PAGE_SIZE_LOG2 = 20,
|
||||
MIN_PAGE_SIZE_LOG2 = 12,
|
||||
SIZE_LOG2 = 14,
|
||||
SIZE = 1 << SIZE_LOG2,
|
||||
ALIGNM_LOG2 = SIZE_LOG2,
|
||||
MAX_PAGE_SIZE_LOG2 = 20,
|
||||
MIN_PAGE_SIZE_LOG2 = 12,
|
||||
TABLE_LEVEL_X_VIRT_SIZE = 1 << MAX_PAGE_SIZE_LOG2,
|
||||
TABLE_LEVEL_X_SIZE_LOG2 = MIN_PAGE_SIZE_LOG2,
|
||||
CORE_VM_AREA_SIZE = 1024 * 1024 * 1024,
|
||||
CORE_TRANS_TABLE_COUNT = CORE_VM_AREA_SIZE / TABLE_LEVEL_X_VIRT_SIZE,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -522,7 +522,25 @@ class Genode::Level_x_translation_table :
|
||||
this->_range_op(vo, 0, size, Remove_func(alloc)); }
|
||||
};
|
||||
|
||||
namespace Genode {
|
||||
class Translation_table : public Level_1_stage_1_translation_table { }; }
|
||||
|
||||
namespace Genode {
|
||||
class Translation_table;
|
||||
}
|
||||
|
||||
class Genode::Translation_table : public Level_1_stage_1_translation_table
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
TABLE_LEVEL_X_SIZE_LOG2 = SIZE_LOG2_4KB,
|
||||
TABLE_LEVEL_X_ENTRIES = (1 << SIZE_LOG2_4KB) / sizeof(addr_t),
|
||||
CORE_VM_AREA_SIZE = 1024 * 1024 * 1024,
|
||||
SIZE_1GB = 1 << SIZE_LOG2_1GB,
|
||||
CORE_LEVEL_2_TT_COUNT = ((uint64_t)CORE_VM_AREA_SIZE +
|
||||
SIZE_1GB - 1) / SIZE_1GB,
|
||||
CORE_TRANS_TABLE_COUNT = CORE_LEVEL_2_TT_COUNT +
|
||||
CORE_LEVEL_2_TT_COUNT *
|
||||
TABLE_LEVEL_X_ENTRIES,
|
||||
};
|
||||
};
|
||||
#endif /* _ARM_V7__LONG_TRANSLATION_TABLE_H_ */
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <util.h>
|
||||
#include <page_flags.h>
|
||||
#include <translation_table_allocator.h>
|
||||
|
||||
@ -634,6 +635,14 @@ class Genode::Pml4_table
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Return how many entries of an alignment fit into region
|
||||
*/
|
||||
static constexpr size_t _count(size_t region, size_t alignment) {
|
||||
return align_addr<size_t>(region, alignment) / (1UL << alignment); }
|
||||
|
||||
public:
|
||||
|
||||
static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4KB;
|
||||
@ -690,7 +699,23 @@ class Genode::Pml4_table
|
||||
}
|
||||
} __attribute__((aligned(1 << ALIGNM_LOG2)));
|
||||
|
||||
|
||||
namespace Genode {
|
||||
class Translation_table : public Pml4_table { }; }
|
||||
class Translation_table;
|
||||
}
|
||||
|
||||
class Genode::Translation_table : public Pml4_table
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
TABLE_LEVEL_X_SIZE_LOG2 = SIZE_LOG2_4KB,
|
||||
CORE_VM_AREA_SIZE = 1024 * 1024 * 1024,
|
||||
CORE_TRANS_TABLE_COUNT =
|
||||
_count(CORE_VM_AREA_SIZE, SIZE_LOG2_512GB)
|
||||
+ _count(CORE_VM_AREA_SIZE, SIZE_LOG2_1GB)
|
||||
+ _count(CORE_VM_AREA_SIZE, SIZE_LOG2_2MB)
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _TRANSLATION_TABLE_H_ */
|
||||
|
@ -14,11 +14,7 @@
|
||||
#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 {
|
||||
|
||||
@ -26,13 +22,6 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
@ -55,107 +44,4 @@ class Genode::Translation_table_allocator : public Genode::Allocator
|
||||
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_ */
|
||||
|
140
repos/base-hw/src/core/include/translation_table_allocator_tpl.h
Normal file
140
repos/base-hw/src/core/include/translation_table_allocator_tpl.h
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* \brief Translation table allocator template implementation
|
||||
* \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_TPL_H_
|
||||
#define _CORE__INCLUDE__TRANSLATION_TABLE_ALLOCATOR_TPL_H_
|
||||
|
||||
#include <base/stdint.h>
|
||||
#include <util/bit_allocator.h>
|
||||
#include <core_mem_alloc.h>
|
||||
#include <translation_table.h>
|
||||
#include <translation_table_allocator.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* Statically dimensioned translation table allocator
|
||||
*
|
||||
* /param TABLES count of tables the allocator provides as maximum
|
||||
*/
|
||||
template <unsigned TABLES> class Translation_table_allocator_tpl;
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
enum { SIZE = 1 << Translation_table::TABLE_LEVEL_X_SIZE_LOG2 };
|
||||
|
||||
uint8_t data[SIZE];
|
||||
};
|
||||
|
||||
Table _tables[TABLES];
|
||||
Allocator _alloc;
|
||||
|
||||
public:
|
||||
|
||||
static constexpr unsigned ALIGN = Table::SIZE;
|
||||
|
||||
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_TPL_H_ */
|
@ -33,13 +33,14 @@ namespace Genode
|
||||
/**
|
||||
* Round down to the minimal page-size alignment
|
||||
*/
|
||||
inline addr_t trunc_page(addr_t addr) { return addr & get_page_mask(); }
|
||||
constexpr addr_t trunc_page(addr_t addr) {
|
||||
return addr & get_page_mask(); }
|
||||
|
||||
|
||||
/**
|
||||
* Round up to the minimal page-size alignment
|
||||
*/
|
||||
inline addr_t round_page(addr_t addr)
|
||||
constexpr addr_t round_page(addr_t addr)
|
||||
{ return trunc_page(addr + get_page_size() - 1); }
|
||||
|
||||
|
||||
|
@ -86,6 +86,14 @@ static void init_alloc(Range_allocator * const alloc,
|
||||
** Platform **
|
||||
**************/
|
||||
|
||||
addr_t Platform::core_translation_tables()
|
||||
{
|
||||
size_t sz = max((size_t)Translation_table::TABLE_LEVEL_X_SIZE_LOG2,
|
||||
get_page_size_log2());
|
||||
return align_addr<addr_t>((addr_t)&_boot_modules_binaries_end, sz);
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_core_only_ram_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _r[] =
|
||||
@ -97,7 +105,10 @@ Native_region * Platform::_core_only_ram_regions(unsigned const i)
|
||||
/* boot modules */
|
||||
{ (addr_t)&_boot_modules_binaries_begin,
|
||||
(size_t)((addr_t)&_boot_modules_binaries_end -
|
||||
(addr_t)&_boot_modules_binaries_begin) }
|
||||
(addr_t)&_boot_modules_binaries_begin) },
|
||||
|
||||
/* translation table allocator */
|
||||
{ core_translation_tables(), core_translation_tables_size() }
|
||||
};
|
||||
return i < sizeof(_r)/sizeof(_r[0]) ? &_r[i] : 0;
|
||||
}
|
||||
|
@ -181,17 +181,15 @@ Translation_table * const Core_platform_pd::_table()
|
||||
|
||||
Translation_table_allocator * const Core_platform_pd::_table_alloc()
|
||||
{
|
||||
/**
|
||||
* Core's translation table allocator should contain as much tables
|
||||
* needed to populate the whole virtual memory available to core.
|
||||
* By now, we do not cover the limitation of core's virtula memory
|
||||
* when opening e.g. sessions on behalf of clients. Therefore, for
|
||||
* the time being the number of tables is set to some reasonable
|
||||
* high number.
|
||||
*/
|
||||
using Pa = Translation_table_allocator_tpl<1024>;
|
||||
static Pa * pa = unmanaged_singleton<Pa, Pa::ALIGN>();
|
||||
return pa->alloc();
|
||||
constexpr size_t count = Genode::Translation_table::CORE_TRANS_TABLE_COUNT;
|
||||
using Allocator = Translation_table_allocator_tpl<count>;
|
||||
|
||||
static Allocator * alloc = nullptr;
|
||||
if (!alloc) {
|
||||
void * base = (void*) Platform::core_translation_tables();
|
||||
alloc = construct_at<Allocator>(base);
|
||||
}
|
||||
return alloc->alloc();
|
||||
}
|
||||
|
||||
|
||||
@ -223,6 +221,11 @@ Core_platform_pd::Core_platform_pd()
|
||||
/* map core's program image */
|
||||
_map((addr_t)&_prog_img_beg, (addr_t)&_prog_img_end, false);
|
||||
|
||||
/* map core's page table allocator */
|
||||
_map(Platform::core_translation_tables(),
|
||||
Platform::core_translation_tables() +
|
||||
Platform::core_translation_tables_size(), false);
|
||||
|
||||
/* map core's mmio regions */
|
||||
Native_region * r = Platform::_core_only_mmio_regions(0);
|
||||
for (unsigned i = 0; r;
|
||||
|
Loading…
x
Reference in New Issue
Block a user