141 lines
3.5 KiB
C++
141 lines
3.5 KiB
C++
/*
|
|
* \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_ */
|