mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
hw: map core on demand (fix #723)
Instead of mapping all physical memory 1:1 into core/kernel's address space, this commit limits the 1:1 mapping to the binary image, and I/O memory regions used by the kernel only. All subsequent memory accesses of core are done by mapping the corresponding memory on demand, and not necessarily 1:1. This commit has several side effects: The page table code had to be revisited completely. The kernel inserts no longer anything into the page tables, apart from the initial translations to have the core/kernel image available when enabling the MMU. The page tables and higher level translation tables are no longer named Tlb, but Translation_table instead. There is no indirection class required to define the translation tables of a concrete SoC, the appropriated ARM specifier is sufficient. The ability to map core's memory the same way like it's done for all other protection domains, makes a special treatment of core's threads (no context area) obsolete. Ref #567 (partly solves it) Fix #723 Fix #1068
This commit is contained in:
parent
34b18e9da2
commit
73eb7a8d4b
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Basic Genode types
|
* \brief Basic Genode types
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-01-02
|
* \date 2012-01-02
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -317,23 +318,12 @@ class Genode::Native_utcb
|
|||||||
|
|
||||||
namespace Genode
|
namespace Genode
|
||||||
{
|
{
|
||||||
enum {
|
static constexpr addr_t VIRT_ADDR_SPACE_START = 0x1000;
|
||||||
VIRT_ADDR_SPACE_START = 0x1000,
|
static constexpr size_t VIRT_ADDR_SPACE_SIZE = 0xfffef000;
|
||||||
VIRT_ADDR_SPACE_SIZE = 0xfffef000,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
static constexpr Native_utcb * UTCB_MAIN_THREAD = (Native_utcb *)
|
||||||
* Return virtual UTCB location of main threads
|
((VIRT_ADDR_SPACE_START + VIRT_ADDR_SPACE_SIZE - sizeof(Native_utcb))
|
||||||
*/
|
& ~((1 << MIN_MAPPING_SIZE_LOG2) - 1));
|
||||||
inline Native_utcb * main_thread_utcb()
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
VAS_TOP = VIRT_ADDR_SPACE_START + VIRT_ADDR_SPACE_SIZE,
|
|
||||||
UTCB = VAS_TOP - sizeof(Native_utcb),
|
|
||||||
UTCB_ALIGNED = UTCB & ~((1 << MIN_MAPPING_SIZE_LOG2) - 1),
|
|
||||||
};
|
|
||||||
return (Native_utcb *)UTCB_ALIGNED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _BASE__NATIVE_TYPES_H_ */
|
#endif /* _BASE__NATIVE_TYPES_H_ */
|
||||||
|
@ -93,7 +93,7 @@ class Genode::Ipc_pager
|
|||||||
*/
|
*/
|
||||||
struct Fault_thread_regs
|
struct Fault_thread_regs
|
||||||
{
|
{
|
||||||
addr_t tlb;
|
addr_t pd;
|
||||||
addr_t ip;
|
addr_t ip;
|
||||||
addr_t addr;
|
addr_t addr;
|
||||||
addr_t writes;
|
addr_t writes;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Thread initialization
|
* \brief Thread initialization
|
||||||
* \author Martin stein
|
* \author Martin stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2013-02-15
|
* \date 2013-02-15
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -14,6 +15,7 @@
|
|||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/thread.h>
|
#include <base/thread.h>
|
||||||
#include <base/env.h>
|
#include <base/env.h>
|
||||||
|
#include <base/sleep.h>
|
||||||
|
|
||||||
/* base-hw includes */
|
/* base-hw includes */
|
||||||
#include <kernel/interface.h>
|
#include <kernel/interface.h>
|
||||||
@ -21,10 +23,7 @@
|
|||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
Ram_dataspace_capability _main_thread_utcb_ds;
|
Ram_dataspace_capability _main_thread_utcb_ds;
|
||||||
|
Native_thread_id _main_thread_id;
|
||||||
Native_thread_id _main_thread_id;
|
|
||||||
|
|
||||||
namespace Genode { Rm_session * env_context_area_rm_session(); }
|
|
||||||
|
|
||||||
|
|
||||||
/**************************
|
/**************************
|
||||||
@ -64,43 +63,25 @@ void prepare_reinit_main_thread() { prepare_init_main_thread(); }
|
|||||||
** Thread_base **
|
** Thread_base **
|
||||||
*****************/
|
*****************/
|
||||||
|
|
||||||
|
extern Native_utcb* main_thread_utcb();
|
||||||
|
|
||||||
|
Native_utcb * Thread_base::utcb()
|
||||||
|
{
|
||||||
|
if (this) { return &_context->utcb; }
|
||||||
|
return main_thread_utcb();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Thread_base::_thread_start()
|
||||||
|
{
|
||||||
|
Thread_base::myself()->_thread_bootstrap();
|
||||||
|
Thread_base::myself()->entry();
|
||||||
|
Thread_base::myself()->_join_lock.unlock();
|
||||||
|
Genode::sleep_forever();
|
||||||
|
}
|
||||||
|
|
||||||
void Thread_base::_thread_bootstrap()
|
void Thread_base::_thread_bootstrap()
|
||||||
{
|
{
|
||||||
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
Native_utcb * const utcb = Thread_base::myself()->utcb();
|
||||||
_tid.thread_id = utcb->start_info()->thread_id();
|
_tid.thread_id = utcb->start_info()->thread_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_init_platform_thread(Type type)
|
|
||||||
{
|
|
||||||
/* if no cpu session is given, use it from the environment */
|
|
||||||
if (!_cpu_session)
|
|
||||||
_cpu_session = env()->cpu_session();
|
|
||||||
|
|
||||||
/* nothing platform specific to do if this is not a special thread */
|
|
||||||
if (type == NORMAL)
|
|
||||||
{
|
|
||||||
/* create server object */
|
|
||||||
char buf[48];
|
|
||||||
name(buf, sizeof(buf));
|
|
||||||
_thread_cap = _cpu_session->create_thread(buf, (addr_t)&_context->utcb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if we got reinitialized we have to get rid of the old UTCB */
|
|
||||||
size_t const utcb_size = sizeof(Native_utcb);
|
|
||||||
addr_t const context_area = Native_config::context_area_virtual_base();
|
|
||||||
addr_t const utcb_new = (addr_t)&_context->utcb - context_area;
|
|
||||||
Rm_session * const rm = env_context_area_rm_session();
|
|
||||||
if (type == REINITIALIZED_MAIN) { rm->detach(utcb_new); }
|
|
||||||
|
|
||||||
/* remap initial main-thread UTCB according to context-area spec */
|
|
||||||
try { rm->attach_at(_main_thread_utcb_ds, utcb_new, utcb_size); }
|
|
||||||
catch(...) {
|
|
||||||
PERR("failed to re-map UTCB");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
/* adjust initial object state in case of a main thread */
|
|
||||||
tid().thread_id = _main_thread_id;
|
|
||||||
_thread_cap = env()->parent()->main_thread_cap();
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* \brief Platform specific parts of the thread API
|
* \brief Platform specific parts of the thread API
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-02-12
|
* \date 2012-02-12
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -21,29 +22,50 @@ using namespace Genode;
|
|||||||
|
|
||||||
namespace Genode { Rm_session * env_context_area_rm_session(); }
|
namespace Genode { Rm_session * env_context_area_rm_session(); }
|
||||||
|
|
||||||
|
extern Ram_dataspace_capability _main_thread_utcb_ds;
|
||||||
|
extern Native_thread_id _main_thread_id;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return virtual UTCB location of main threads
|
||||||
|
*/
|
||||||
|
Native_utcb * main_thread_utcb() { return UTCB_MAIN_THREAD; }
|
||||||
|
|
||||||
|
|
||||||
/*****************
|
/*****************
|
||||||
** Thread_base **
|
** Thread_base **
|
||||||
*****************/
|
*****************/
|
||||||
|
|
||||||
Native_utcb * Thread_base::utcb()
|
void Thread_base::_init_platform_thread(Type type)
|
||||||
{
|
{
|
||||||
if (this) { return &_context->utcb; }
|
if (type == NORMAL) { return; }
|
||||||
return main_thread_utcb();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* if we got reinitialized we have to get rid of the old UTCB */
|
||||||
|
size_t const utcb_size = sizeof(Native_utcb);
|
||||||
|
addr_t const context_area = Native_config::context_area_virtual_base();
|
||||||
|
addr_t const utcb_new = (addr_t)&_context->utcb - context_area;
|
||||||
|
Rm_session * const rm = env_context_area_rm_session();
|
||||||
|
if (type == REINITIALIZED_MAIN) { rm->detach(utcb_new); }
|
||||||
|
|
||||||
void Thread_base::_thread_start()
|
/* remap initial main-thread UTCB according to context-area spec */
|
||||||
{
|
try { rm->attach_at(_main_thread_utcb_ds, utcb_new, utcb_size); }
|
||||||
Thread_base::myself()->_thread_bootstrap();
|
catch(...) {
|
||||||
Thread_base::myself()->entry();
|
PERR("failed to re-map UTCB");
|
||||||
Thread_base::myself()->_join_lock.unlock();
|
while (1) ;
|
||||||
Genode::sleep_forever();
|
}
|
||||||
|
/* adjust initial object state in case of a main thread */
|
||||||
|
tid().thread_id = _main_thread_id;
|
||||||
|
_thread_cap = env()->parent()->main_thread_cap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_deinit_platform_thread()
|
void Thread_base::_deinit_platform_thread()
|
||||||
{
|
{
|
||||||
|
if (!_cpu_session)
|
||||||
|
_cpu_session = env()->cpu_session();
|
||||||
|
|
||||||
|
_cpu_session->kill_thread(_thread_cap);
|
||||||
|
|
||||||
/* detach userland thread-context */
|
/* detach userland thread-context */
|
||||||
size_t const size = sizeof(_context->utcb);
|
size_t const size = sizeof(_context->utcb);
|
||||||
addr_t utcb = Context_allocator::addr_to_base(_context) +
|
addr_t utcb = Context_allocator::addr_to_base(_context) +
|
||||||
@ -51,8 +73,6 @@ void Thread_base::_deinit_platform_thread()
|
|||||||
Native_config::context_area_virtual_base();
|
Native_config::context_area_virtual_base();
|
||||||
env_context_area_rm_session()->detach(utcb);
|
env_context_area_rm_session()->detach(utcb);
|
||||||
|
|
||||||
/* destroy server object */
|
|
||||||
_cpu_session->kill_thread(_thread_cap);
|
|
||||||
if (_pager_cap.valid()) {
|
if (_pager_cap.valid()) {
|
||||||
env()->rm_session()->remove_client(_pager_cap);
|
env()->rm_session()->remove_client(_pager_cap);
|
||||||
}
|
}
|
||||||
@ -61,6 +81,14 @@ void Thread_base::_deinit_platform_thread()
|
|||||||
|
|
||||||
void Thread_base::start()
|
void Thread_base::start()
|
||||||
{
|
{
|
||||||
|
if (!_cpu_session)
|
||||||
|
_cpu_session = env()->cpu_session();
|
||||||
|
|
||||||
|
/* create server object */
|
||||||
|
char buf[48];
|
||||||
|
name(buf, sizeof(buf));
|
||||||
|
_thread_cap = _cpu_session->create_thread(buf, (addr_t)&_context->utcb);
|
||||||
|
|
||||||
/* assign thread to protection domain */
|
/* assign thread to protection domain */
|
||||||
env()->pd_session()->bind_thread(_thread_cap);
|
env()->pd_session()->bind_thread(_thread_cap);
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief CPU specific implementations of core
|
* \brief CPU specific implementations of core
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2013-11-11
|
* \date 2013-11-11
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ using namespace Kernel;
|
|||||||
Thread_cpu_support::Thread_cpu_support(Thread * const t)
|
Thread_cpu_support::Thread_cpu_support(Thread * const t)
|
||||||
:
|
:
|
||||||
_fault(t),
|
_fault(t),
|
||||||
_fault_tlb(0),
|
_fault_pd(0),
|
||||||
_fault_addr(0),
|
_fault_addr(0),
|
||||||
_fault_writes(0),
|
_fault_writes(0),
|
||||||
_fault_signal(0)
|
_fault_signal(0)
|
||||||
@ -57,7 +58,7 @@ addr_t Thread::* Thread::_reg(addr_t const id) const
|
|||||||
/* [15] */ (addr_t Thread::*)&Thread::ip,
|
/* [15] */ (addr_t Thread::*)&Thread::ip,
|
||||||
/* [16] */ (addr_t Thread::*)&Thread::cpsr,
|
/* [16] */ (addr_t Thread::*)&Thread::cpsr,
|
||||||
/* [17] */ (addr_t Thread::*)&Thread::cpu_exception,
|
/* [17] */ (addr_t Thread::*)&Thread::cpu_exception,
|
||||||
/* [18] */ (addr_t Thread::*)&Thread::_fault_tlb,
|
/* [18] */ (addr_t Thread::*)&Thread::_fault_pd,
|
||||||
/* [19] */ (addr_t Thread::*)&Thread::_fault_addr,
|
/* [19] */ (addr_t Thread::*)&Thread::_fault_addr,
|
||||||
/* [20] */ (addr_t Thread::*)&Thread::_fault_writes,
|
/* [20] */ (addr_t Thread::*)&Thread::_fault_writes,
|
||||||
/* [21] */ (addr_t Thread::*)&Thread::_fault_signal
|
/* [21] */ (addr_t Thread::*)&Thread::_fault_signal
|
||||||
@ -79,7 +80,7 @@ void Thread::_mmu_exception()
|
|||||||
{
|
{
|
||||||
_unschedule(AWAITS_RESUME);
|
_unschedule(AWAITS_RESUME);
|
||||||
if (in_fault(_fault_addr, _fault_writes)) {
|
if (in_fault(_fault_addr, _fault_writes)) {
|
||||||
_fault_tlb = (addr_t)_pd->tlb();
|
_fault_pd = (addr_t)_pd->platform_pd();
|
||||||
_fault_signal = _fault.signal_context_id();
|
_fault_signal = _fault.signal_context_id();
|
||||||
_fault.submit();
|
_fault.submit();
|
||||||
return;
|
return;
|
||||||
@ -113,4 +114,4 @@ addr_t const * cpu_state_regs() { return _cpu_state_regs; }
|
|||||||
size_t cpu_state_regs_length()
|
size_t cpu_state_regs_length()
|
||||||
{
|
{
|
||||||
return sizeof(_cpu_state_regs)/sizeof(_cpu_state_regs[0]);
|
return sizeof(_cpu_state_regs)/sizeof(_cpu_state_regs[0]);
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class Kernel::Thread_cpu_support
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
Thread_event _fault;
|
Thread_event _fault;
|
||||||
addr_t _fault_tlb;
|
addr_t _fault_pd;
|
||||||
addr_t _fault_addr;
|
addr_t _fault_addr;
|
||||||
addr_t _fault_writes;
|
addr_t _fault_writes;
|
||||||
addr_t _fault_signal;
|
addr_t _fault_signal;
|
||||||
|
674
base-hw/src/core/arm/short_translation_table.h
Normal file
674
base-hw/src/core/arm/short_translation_table.h
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
/*
|
||||||
|
* \brief Short descriptor translation table definitions
|
||||||
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2012-02-22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 _ARM__SHORT_TRANSLATION_TABLE_H_
|
||||||
|
#define _ARM__SHORT_TRANSLATION_TABLE_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/register.h>
|
||||||
|
#include <base/printf.h>
|
||||||
|
|
||||||
|
/* base-hw includes */
|
||||||
|
#include <page_flags.h>
|
||||||
|
#include <page_slab.h>
|
||||||
|
|
||||||
|
namespace Arm
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if 'p' is aligned to 1 << 'alignm_log2'
|
||||||
|
*/
|
||||||
|
inline bool aligned(addr_t const a, size_t const alignm_log2) {
|
||||||
|
return a == ((a >> alignm_log2) << alignm_log2); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return permission configuration according to given mapping flags
|
||||||
|
*
|
||||||
|
* \param T targeted translation-table-descriptor type
|
||||||
|
* \param flags mapping flags
|
||||||
|
*
|
||||||
|
* \return descriptor value with AP and XN set and the rest left zero
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
static typename T::access_t
|
||||||
|
access_permission_bits(Page_flags const & flags)
|
||||||
|
{
|
||||||
|
typedef typename T::Xn Xn;
|
||||||
|
typedef typename T::Ap Ap;
|
||||||
|
typedef typename T::access_t access_t;
|
||||||
|
bool const w = flags.writeable;
|
||||||
|
bool const p = flags.privileged;
|
||||||
|
access_t ap;
|
||||||
|
if (w) { if (p) { ap = Ap::bits(0b001); }
|
||||||
|
else { ap = Ap::bits(0b011); }
|
||||||
|
} else { if (p) { ap = Ap::bits(0b101); }
|
||||||
|
else { ap = Ap::bits(0b010); }
|
||||||
|
}
|
||||||
|
return Xn::bits(!flags.executable) | ap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Memory region attributes for the translation descriptor 'T'
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
static typename T::access_t
|
||||||
|
memory_region_attr(Page_flags const & flags);
|
||||||
|
|
||||||
|
class Section_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First level translation table
|
||||||
|
*/
|
||||||
|
class Arm::Section_table
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/***************************
|
||||||
|
** Exception definitions **
|
||||||
|
***************************/
|
||||||
|
|
||||||
|
class Double_insertion {};
|
||||||
|
class Misaligned {};
|
||||||
|
class Invalid_range {};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Second level translation table
|
||||||
|
*/
|
||||||
|
class Page_table
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SIZE_LOG2 = 10,
|
||||||
|
SIZE = 1 << SIZE_LOG2,
|
||||||
|
ALIGNM_LOG2 = SIZE_LOG2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common descriptor structure
|
||||||
|
*/
|
||||||
|
struct Descriptor : Register<32>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Descriptor types
|
||||||
|
*/
|
||||||
|
enum Type { FAULT, SMALL_PAGE };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VIRT_SIZE_LOG2 = 12,
|
||||||
|
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
||||||
|
VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1,
|
||||||
|
VIRT_BASE_MASK = ~(VIRT_OFFSET_MASK),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Type_0 : Bitfield<0, 2> { };
|
||||||
|
struct Type_1 : Bitfield<1, 1> { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get descriptor type of 'v'
|
||||||
|
*/
|
||||||
|
static Type type(access_t const v)
|
||||||
|
{
|
||||||
|
access_t const t0 = Type_0::get(v);
|
||||||
|
if (t0 == 0) { return FAULT; }
|
||||||
|
access_t const t1 = Type_1::get(v);
|
||||||
|
if (t1 == 1) return SMALL_PAGE;
|
||||||
|
return FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set descriptor type of 'v'
|
||||||
|
*/
|
||||||
|
static void type(access_t & v, Type const t)
|
||||||
|
{
|
||||||
|
switch (t) {
|
||||||
|
case FAULT:
|
||||||
|
Type_0::set(v, 0);
|
||||||
|
return;
|
||||||
|
case SMALL_PAGE:
|
||||||
|
Type_1::set(v, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate descriptor 'v'
|
||||||
|
*/
|
||||||
|
static void invalidate(access_t & v) { type(v, FAULT); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if descriptor 'v' is valid
|
||||||
|
*/
|
||||||
|
static bool valid(access_t & v) {
|
||||||
|
return type(v) != FAULT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small page descriptor structure
|
||||||
|
*/
|
||||||
|
struct Small_page : Descriptor
|
||||||
|
{
|
||||||
|
struct Xn : Bitfield<0, 1> { }; /* execute never */
|
||||||
|
struct B : Bitfield<2, 1> { }; /* mem region attr. */
|
||||||
|
struct C : Bitfield<3, 1> { }; /* mem region attr. */
|
||||||
|
struct Ap_0 : Bitfield<4, 2> { }; /* access permission */
|
||||||
|
struct Tex : Bitfield<6, 3> { }; /* mem region attr. */
|
||||||
|
struct Ap_1 : Bitfield<9, 1> { }; /* access permission */
|
||||||
|
struct S : Bitfield<10, 1> { }; /* shareable bit */
|
||||||
|
struct Ng : Bitfield<11, 1> { }; /* not global bit */
|
||||||
|
struct Pa : Bitfield<12, 20> { }; /* physical base */
|
||||||
|
|
||||||
|
struct Ap : Bitset_2<Ap_0, Ap_1> { }; /* access permission */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose descriptor value
|
||||||
|
*/
|
||||||
|
static access_t create(Page_flags const & flags,
|
||||||
|
addr_t const pa)
|
||||||
|
{
|
||||||
|
access_t v = access_permission_bits<Small_page>(flags);
|
||||||
|
v |= memory_region_attr<Small_page>(flags);
|
||||||
|
v |= Ng::bits(!flags.global);
|
||||||
|
v |= S::bits(1);
|
||||||
|
v |= Pa::masked(pa);
|
||||||
|
Descriptor::type(v, Descriptor::SMALL_PAGE);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Table payload
|
||||||
|
*
|
||||||
|
* Must be the only member of this class
|
||||||
|
*/
|
||||||
|
Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)];
|
||||||
|
|
||||||
|
enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get entry index by virtual offset
|
||||||
|
*
|
||||||
|
* \param i is overridden with the index if call returns 0
|
||||||
|
* \param vo virtual offset relative to the virtual table base
|
||||||
|
*
|
||||||
|
* \retval 0 on success
|
||||||
|
* \retval <0 translation failed
|
||||||
|
*/
|
||||||
|
bool _index_by_vo (unsigned & i, addr_t const vo) const
|
||||||
|
{
|
||||||
|
if (vo > max_virt_offset()) return false;
|
||||||
|
i = vo >> Descriptor::VIRT_SIZE_LOG2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Page_table()
|
||||||
|
{
|
||||||
|
if (!aligned((addr_t)this, ALIGNM_LOG2))
|
||||||
|
throw Misaligned();
|
||||||
|
|
||||||
|
/* start with an empty table */
|
||||||
|
memset(&_entries, 0, sizeof(_entries));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum virtual offset that can be translated by this table
|
||||||
|
*/
|
||||||
|
static addr_t max_virt_offset()
|
||||||
|
{
|
||||||
|
return (MAX_INDEX << Descriptor::VIRT_SIZE_LOG2)
|
||||||
|
+ (Descriptor::VIRT_SIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert one atomic translation 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
|
||||||
|
*
|
||||||
|
* This method overrides an existing translation in case
|
||||||
|
* that it spans the the same virtual range otherwise it
|
||||||
|
* throws a Double_insertion.
|
||||||
|
*/
|
||||||
|
void insert_translation(addr_t vo,
|
||||||
|
addr_t pa,
|
||||||
|
size_t size,
|
||||||
|
Page_flags const & flags)
|
||||||
|
{
|
||||||
|
constexpr size_t sz = Descriptor::VIRT_SIZE;
|
||||||
|
|
||||||
|
for (unsigned i; (size > 0) && _index_by_vo (i, vo);
|
||||||
|
size = (size < sz) ? 0 : size - sz, vo += sz, pa += sz) {
|
||||||
|
|
||||||
|
if (Descriptor::valid(_entries[i]) &&
|
||||||
|
_entries[i] != Small_page::create(flags, pa))
|
||||||
|
throw Double_insertion();
|
||||||
|
|
||||||
|
/* compose new descriptor value */
|
||||||
|
_entries[i] = Small_page::create(flags, pa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove translations that overlap with a given virtual region
|
||||||
|
*
|
||||||
|
* \param vo region offset within the tables virtual region
|
||||||
|
* \param size region size
|
||||||
|
*/
|
||||||
|
void remove_translation(addr_t vo, size_t size)
|
||||||
|
{
|
||||||
|
constexpr size_t sz = Descriptor::VIRT_SIZE;
|
||||||
|
|
||||||
|
for (unsigned i; (size > 0) && _index_by_vo(i, vo);
|
||||||
|
size = (size < sz) ? 0 : size - sz, vo += sz) {
|
||||||
|
|
||||||
|
switch (Descriptor::type(_entries[i])) {
|
||||||
|
|
||||||
|
case Descriptor::SMALL_PAGE:
|
||||||
|
{
|
||||||
|
Descriptor::invalidate(_entries[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this table solely contain invalid entries
|
||||||
|
*/
|
||||||
|
bool empty()
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
||||||
|
if (Descriptor::valid(_entries[i])) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} __attribute__((aligned(1<<Page_table::ALIGNM_LOG2)));
|
||||||
|
|
||||||
|
|
||||||
|
enum { DOMAIN = 0 };
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SIZE_LOG2 = 14,
|
||||||
|
SIZE = 1 << SIZE_LOG2,
|
||||||
|
ALIGNM_LOG2 = SIZE_LOG2,
|
||||||
|
|
||||||
|
MAX_COSTS_PER_TRANSLATION = sizeof(Page_table),
|
||||||
|
|
||||||
|
MAX_PAGE_SIZE_LOG2 = 20,
|
||||||
|
MIN_PAGE_SIZE_LOG2 = 12,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A first level translation descriptor
|
||||||
|
*/
|
||||||
|
struct Descriptor : Register<32>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Descriptor types
|
||||||
|
*/
|
||||||
|
enum Type { FAULT, PAGE_TABLE, SECTION };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VIRT_SIZE_LOG2 = 20,
|
||||||
|
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
||||||
|
VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1,
|
||||||
|
VIRT_BASE_MASK = ~VIRT_OFFSET_MASK,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Type_0 : Bitfield<0, 2> { };
|
||||||
|
struct Type_1_0 : Bitfield<1, 1> { };
|
||||||
|
struct Type_1_1 : Bitfield<18, 1> { };
|
||||||
|
struct Type_1 : Bitset_2<Type_1_0, Type_1_1> { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get descriptor type of 'v'
|
||||||
|
*/
|
||||||
|
static Type type(access_t const v)
|
||||||
|
{
|
||||||
|
switch (Type_0::get(v)) {
|
||||||
|
case 0: return FAULT;
|
||||||
|
case 1: return PAGE_TABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Type_1::get(v)) {
|
||||||
|
case 1: return SECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set descriptor type of 'v'
|
||||||
|
*/
|
||||||
|
static void type(access_t & v, Type const t)
|
||||||
|
{
|
||||||
|
switch (t) {
|
||||||
|
case FAULT:
|
||||||
|
Type_0::set(v, 0);
|
||||||
|
return;
|
||||||
|
case PAGE_TABLE:
|
||||||
|
Type_0::set(v, 1);
|
||||||
|
return;
|
||||||
|
case SECTION:
|
||||||
|
Type_1::set(v, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate descriptor 'v'
|
||||||
|
*/
|
||||||
|
static void invalidate(access_t & v) { type(v, FAULT); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if descriptor 'v' is valid
|
||||||
|
*/
|
||||||
|
static bool valid(access_t & v) { return type(v) != FAULT; }
|
||||||
|
|
||||||
|
static inline Type align(addr_t vo, size_t size)
|
||||||
|
{
|
||||||
|
return ((vo & VIRT_OFFSET_MASK) || size < VIRT_SIZE)
|
||||||
|
? PAGE_TABLE : SECTION;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to a second level translation table
|
||||||
|
*/
|
||||||
|
struct Page_table_descriptor : Descriptor
|
||||||
|
{
|
||||||
|
struct Domain : Bitfield<5, 4> { }; /* domain */
|
||||||
|
struct Pa : Bitfield<10, 22> { }; /* physical base */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose descriptor value
|
||||||
|
*/
|
||||||
|
static access_t create(Page_table * const pt)
|
||||||
|
{
|
||||||
|
access_t v = Domain::bits(DOMAIN) |
|
||||||
|
Pa::masked((addr_t)pt);
|
||||||
|
Descriptor::type(v, Descriptor::PAGE_TABLE);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Section translation descriptor
|
||||||
|
*/
|
||||||
|
struct Section : Descriptor
|
||||||
|
{
|
||||||
|
struct B : Bitfield<2, 1> { }; /* mem. region attr. */
|
||||||
|
struct C : Bitfield<3, 1> { }; /* mem. region attr. */
|
||||||
|
struct Xn : Bitfield<4, 1> { }; /* execute never bit */
|
||||||
|
struct Domain : Bitfield<5, 4> { }; /* domain */
|
||||||
|
struct Ap_0 : Bitfield<10, 2> { }; /* access permission */
|
||||||
|
struct Tex : Bitfield<12, 3> { }; /* mem. region attr. */
|
||||||
|
struct Ap_1 : Bitfield<15, 1> { }; /* access permission */
|
||||||
|
struct S : Bitfield<16, 1> { }; /* shared */
|
||||||
|
struct Ng : Bitfield<17, 1> { }; /* not global */
|
||||||
|
struct Pa : Bitfield<20, 12> { }; /* physical base */
|
||||||
|
struct Ap : Bitset_2<Ap_0, Ap_1> { }; /* access permission */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose descriptor value
|
||||||
|
*/
|
||||||
|
static access_t create(Page_flags const & flags,
|
||||||
|
addr_t const pa)
|
||||||
|
{
|
||||||
|
access_t v = access_permission_bits<Section>(flags);
|
||||||
|
v |= memory_region_attr<Section>(flags);
|
||||||
|
v |= Domain::bits(DOMAIN);
|
||||||
|
v |= S::bits(1);
|
||||||
|
v |= Ng::bits(!flags.global);
|
||||||
|
v |= Pa::masked(pa);
|
||||||
|
Descriptor::type(v, Descriptor::SECTION);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/* table payload, must be the first member of this class */
|
||||||
|
Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)];
|
||||||
|
|
||||||
|
enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get entry index by virtual offset
|
||||||
|
*
|
||||||
|
* \param i is overridden with the resulting index
|
||||||
|
* \param vo offset within the virtual region represented
|
||||||
|
* by this table
|
||||||
|
*
|
||||||
|
* \retval 0 on success
|
||||||
|
* \retval <0 if virtual offset couldn't be resolved,
|
||||||
|
* in this case 'i' reside invalid
|
||||||
|
*/
|
||||||
|
bool _index_by_vo(unsigned & i, addr_t const vo) const
|
||||||
|
{
|
||||||
|
if (vo > max_virt_offset()) return false;
|
||||||
|
i = vo >> Descriptor::VIRT_SIZE_LOG2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a second level translation at the given entry index
|
||||||
|
*
|
||||||
|
* \param i the related index
|
||||||
|
* \param vo virtual start address of range
|
||||||
|
* \param pa physical start address of range
|
||||||
|
* \param size size of range
|
||||||
|
* \param flags mapping flags
|
||||||
|
* \param slab second level page slab 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 * slab)
|
||||||
|
{
|
||||||
|
Page_table * pt = 0;
|
||||||
|
switch (Descriptor::type(_entries[i])) {
|
||||||
|
|
||||||
|
case Descriptor::FAULT:
|
||||||
|
{
|
||||||
|
if (!slab) 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_phys = pt_phys ? pt_phys : pt; /* hack for core */
|
||||||
|
_entries[i] = Page_table_descriptor::create(pt_phys);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Descriptor::PAGE_TABLE:
|
||||||
|
{
|
||||||
|
/* use allocator to retrieve virtual address of page table */
|
||||||
|
void * pt_phys = (void*)
|
||||||
|
Page_table_descriptor::Pa::masked(_entries[i]);
|
||||||
|
pt = (Page_table *) slab->virt_addr(pt_phys);
|
||||||
|
pt = pt ? pt : (Page_table *)pt_phys ; /* hack for core */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw Double_insertion();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* insert translation */
|
||||||
|
pt->insert_translation(vo - Section::Pa::masked(vo),
|
||||||
|
pa, size, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Placement new
|
||||||
|
*/
|
||||||
|
void * operator new (size_t, void * p) { return p; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Section_table()
|
||||||
|
{
|
||||||
|
if (!aligned((addr_t)this, ALIGNM_LOG2))
|
||||||
|
throw Misaligned();
|
||||||
|
|
||||||
|
/* start with an empty table */
|
||||||
|
memset(&_entries, 0, sizeof(_entries));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum virtual offset that can be translated by this table
|
||||||
|
*/
|
||||||
|
static addr_t max_virt_offset()
|
||||||
|
{
|
||||||
|
return (MAX_INDEX << Descriptor::VIRT_SIZE_LOG2)
|
||||||
|
+ (Descriptor::VIRT_SIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void insert_translation(addr_t vo,
|
||||||
|
addr_t pa,
|
||||||
|
size_t size,
|
||||||
|
Page_flags const & flags,
|
||||||
|
Page_slab * slab)
|
||||||
|
{
|
||||||
|
/* sanity check */
|
||||||
|
if ((vo & Page_table::Descriptor::VIRT_OFFSET_MASK)
|
||||||
|
|| size < Page_table::Descriptor::VIRT_SIZE)
|
||||||
|
throw Invalid_range();
|
||||||
|
|
||||||
|
for (unsigned i; (size > 0) && _index_by_vo (i, vo);) {
|
||||||
|
|
||||||
|
addr_t end = (vo + Descriptor::VIRT_SIZE)
|
||||||
|
& Descriptor::VIRT_BASE_MASK;
|
||||||
|
|
||||||
|
/* decide granularity of entry that can be inserted */
|
||||||
|
switch (Descriptor::align(vo, size)) {
|
||||||
|
|
||||||
|
case Descriptor::SECTION:
|
||||||
|
{
|
||||||
|
if (Descriptor::valid(_entries[i]) &&
|
||||||
|
_entries[i] != Section::create(flags, pa))
|
||||||
|
throw Double_insertion();
|
||||||
|
_entries[i] = Section::create(flags, pa);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
_insert_second_level(i, vo, pa, min(size, end-vo), flags, slab);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* check whether we wrap */
|
||||||
|
if (end < vo) return;
|
||||||
|
|
||||||
|
size_t sz = end - vo;
|
||||||
|
size = (size > sz) ? size - sz : 0;
|
||||||
|
vo += sz;
|
||||||
|
pa += sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void remove_translation(addr_t vo, size_t size, Page_slab * slab)
|
||||||
|
{
|
||||||
|
if (vo > (vo + size)) throw Invalid_range();
|
||||||
|
|
||||||
|
for (unsigned i; (size > 0) && _index_by_vo(i, vo);) {
|
||||||
|
|
||||||
|
addr_t end = (vo + Descriptor::VIRT_SIZE)
|
||||||
|
& Descriptor::VIRT_BASE_MASK;
|
||||||
|
|
||||||
|
switch (Descriptor::type(_entries[i])) {
|
||||||
|
|
||||||
|
case Descriptor::PAGE_TABLE:
|
||||||
|
{
|
||||||
|
typedef Page_table_descriptor Ptd;
|
||||||
|
typedef Page_table Pt;
|
||||||
|
|
||||||
|
Pt * pt_phys = (Pt *) Ptd::Pa::masked(_entries[i]);
|
||||||
|
Pt * pt = (Pt *) slab->virt_addr(pt_phys);
|
||||||
|
pt = pt ? pt : pt_phys; // TODO hack for core
|
||||||
|
|
||||||
|
addr_t const pt_vo = vo - Section::Pa::masked(vo);
|
||||||
|
pt->remove_translation(pt_vo, min(size, end-vo));
|
||||||
|
|
||||||
|
if (pt->empty()) {
|
||||||
|
Descriptor::invalidate(_entries[i]);
|
||||||
|
destroy(slab, pt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Descriptor::invalidate(_entries[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check whether we wrap */
|
||||||
|
if (end < vo) return;
|
||||||
|
|
||||||
|
size_t sz = end - vo;
|
||||||
|
size = (size > sz) ? size - sz : 0;
|
||||||
|
vo += sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} __attribute__((aligned(1<<Section_table::ALIGNM_LOG2)));
|
||||||
|
|
||||||
|
namespace Genode { using Translation_table = Arm::Section_table; }
|
||||||
|
|
||||||
|
#endif /* _ARM__SHORT_TRANSLATION_TABLE_H_ */
|
||||||
|
|
33
base-hw/src/core/arm_v6/translation_table.h
Normal file
33
base-hw/src/core/arm_v6/translation_table.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* \brief Armv6 translation table for core
|
||||||
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2012-02-22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 _ARM_V6__TRANSLATION_TABLE_H_
|
||||||
|
#define _ARM_V6__TRANSLATION_TABLE_H_
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <arm/short_translation_table.h>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static typename T::access_t
|
||||||
|
Arm::memory_region_attr(Page_flags const & flags)
|
||||||
|
{
|
||||||
|
typedef typename T::Tex Tex;
|
||||||
|
typedef typename T::C C;
|
||||||
|
typedef typename T::B B;
|
||||||
|
if(flags.device) { return 0; }
|
||||||
|
if(flags.cacheable) { return Tex::bits(5) | B::bits(1); }
|
||||||
|
return Tex::bits(6) | C::bits(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _ARM_V6__TRANSLATION_TABLE_H_ */
|
33
base-hw/src/core/arm_v7/translation_table.h
Normal file
33
base-hw/src/core/arm_v7/translation_table.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* \brief Armv7 translation table definitions for core
|
||||||
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2012-02-22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 _ARM_V7__TRANSLATION_TABLE_H_
|
||||||
|
#define _ARM_V7__TRANSLATION_TABLE_H_
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <arm/short_translation_table.h>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static typename T::access_t
|
||||||
|
Arm::memory_region_attr(Page_flags const & flags)
|
||||||
|
{
|
||||||
|
typedef typename T::Tex Tex;
|
||||||
|
typedef typename T::C C;
|
||||||
|
typedef typename T::B B;
|
||||||
|
if (flags.device) { return Tex::bits(2); }
|
||||||
|
if (flags.cacheable) { return Tex::bits(5) | B::bits(1); }
|
||||||
|
return Tex::bits(6) | C::bits(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _ARM_V7__TRANSLATION_TABLE_H_ */
|
@ -47,6 +47,7 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i)
|
|||||||
{
|
{
|
||||||
{ Board::GIC_CPU_MMIO_BASE, Board::GIC_CPU_MMIO_SIZE },
|
{ Board::GIC_CPU_MMIO_BASE, Board::GIC_CPU_MMIO_SIZE },
|
||||||
{ Board::MCT_MMIO_BASE, Board::MCT_MMIO_SIZE },
|
{ Board::MCT_MMIO_BASE, Board::MCT_MMIO_SIZE },
|
||||||
|
{ Board::UART_2_MMIO_BASE, 0x1000 },
|
||||||
};
|
};
|
||||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||||
}
|
}
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Support code for the thread API
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2013-05-07
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <rm_session/rm_session.h>
|
|
||||||
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return single instance of the context-area RM-session
|
|
||||||
*
|
|
||||||
* In base-hw core this object is never used because contexts
|
|
||||||
* get allocated through the phys-mem allocator. Anyways the
|
|
||||||
* accessor must exist because generic main-thread startup calls
|
|
||||||
* it to ensure that common allocations do not steal context area.
|
|
||||||
*/
|
|
||||||
namespace Genode { Rm_session * env_context_area_rm_session() { return 0; } }
|
|
||||||
|
|
66
base-hw/src/core/core_rm_session.cc
Normal file
66
base-hw/src/core/core_rm_session.cc
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* \brief hw-specific implementation of core-local RM session
|
||||||
|
* \author Norman Feske
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2014-02-26
|
||||||
|
*
|
||||||
|
* Taken from OKL4-specific imlementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <platform.h>
|
||||||
|
#include <core_rm_session.h>
|
||||||
|
#include <map_local.h>
|
||||||
|
#include <util.h>
|
||||||
|
#include <base/heap.h>
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
Rm_session::Local_addr
|
||||||
|
Core_rm_session::attach(Dataspace_capability ds_cap, size_t size,
|
||||||
|
off_t offset, bool use_local_addr,
|
||||||
|
Rm_session::Local_addr, bool executable)
|
||||||
|
{
|
||||||
|
Object_pool<Dataspace_component>::Guard ds(_ds_ep->lookup_and_lock(ds_cap));
|
||||||
|
if (!ds)
|
||||||
|
throw Invalid_dataspace();
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
size = ds->size();
|
||||||
|
|
||||||
|
size_t page_rounded_size = (size + get_page_size() - 1) & get_page_mask();
|
||||||
|
|
||||||
|
if (use_local_addr) {
|
||||||
|
PERR("Parameter 'use_local_addr' not supported within core");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset) {
|
||||||
|
PERR("Parameter 'offset' not supported within core");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate range in core's virtual address space */
|
||||||
|
void *virt_addr;
|
||||||
|
if (!platform()->region_alloc()->alloc_aligned(page_rounded_size,
|
||||||
|
&virt_addr,
|
||||||
|
get_page_size_log2()).is_ok()) {
|
||||||
|
PERR("Could not allocate virtual address range in core of size %zd\n",
|
||||||
|
page_rounded_size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* map the dataspace's physical pages to corresponding virtual addresses */
|
||||||
|
unsigned num_pages = page_rounded_size >> get_page_size_log2();
|
||||||
|
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return virt_addr;
|
||||||
|
}
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Translation lookaside buffer
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2012-04-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2012 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 _EXYNOS5__TLB_H_
|
|
||||||
#define _EXYNOS5__TLB_H_
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <board.h>
|
|
||||||
#include <tlb/arm_v7.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
class Tlb : public Arm_v7::Section_table { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation lookaside buffer of core
|
|
||||||
*/
|
|
||||||
class Core_tlb : public Tlb
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor - ensures that core never gets a pagefault
|
|
||||||
*/
|
|
||||||
Core_tlb()
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
|
||||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _EXYNOS5__TLB_H_ */
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Translation lookaside buffer
|
|
||||||
* \author Norman Feske
|
|
||||||
* \author Martin stein
|
|
||||||
* \date 2012-08-30
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _IMX31__TLB_H_
|
|
||||||
#define _IMX31__TLB_H_
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <tlb/arm_v6.h>
|
|
||||||
#include <board.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
class Tlb : public Arm_v6::Section_table { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation lookaside buffer of core
|
|
||||||
*/
|
|
||||||
class Core_tlb : public Tlb
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor - ensures that core never gets a pagefault
|
|
||||||
*/
|
|
||||||
Core_tlb()
|
|
||||||
{
|
|
||||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
|
||||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _IMX31__TLB_H_ */
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Translation lookaside buffer
|
|
||||||
* \author Stefan Kalkowski
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2012-10-24
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _IMX53__TLB_H_
|
|
||||||
#define _IMX53__TLB_H_
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <board.h>
|
|
||||||
#include <tlb/arm_v7.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
class Tlb : public Arm_v7::Section_table { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation lookaside buffer of core
|
|
||||||
*/
|
|
||||||
class Core_tlb : public Tlb
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor - ensures that core never gets a pagefault
|
|
||||||
*/
|
|
||||||
Core_tlb()
|
|
||||||
{
|
|
||||||
map_core_area(Board::RAM0_BASE, Board::RAM0_SIZE, 0);
|
|
||||||
map_core_area(Board::RAM1_BASE, Board::RAM1_SIZE, 0);
|
|
||||||
map_core_area(Board::MMIO_BASE, Board::MMIO_SIZE, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _IMX53__TLB_H_ */
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Translation lookaside buffer
|
|
||||||
* \author Stefan Kalkowski
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2012-10-24
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _IMX53__TLB_H_
|
|
||||||
#define _IMX53__TLB_H_
|
|
||||||
|
|
||||||
#include <drivers/trustzone.h>
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <board.h>
|
|
||||||
#include <tlb/arm_v7.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
class Tlb : public Arm_v7::Section_table { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation lookaside buffer of core
|
|
||||||
*/
|
|
||||||
class Core_tlb : public Tlb
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor - ensures that core never gets a pagefault
|
|
||||||
*/
|
|
||||||
Core_tlb()
|
|
||||||
{
|
|
||||||
map_core_area(Trustzone::SECURE_RAM_BASE,
|
|
||||||
Trustzone::SECURE_RAM_SIZE, 0);
|
|
||||||
map_core_area(Board::MMIO_BASE, Board::MMIO_SIZE, 1);
|
|
||||||
map_core_area(Trustzone::VM_STATE_BASE,
|
|
||||||
Trustzone::VM_STATE_SIZE, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _IMX53__TLB_H_ */
|
|
||||||
|
|
61
base-hw/src/core/include/core_rm_session.h
Normal file
61
base-hw/src/core/include/core_rm_session.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* \brief OKL4-specific core-local region manager session
|
||||||
|
* \author Norman Feske
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2009-04-02
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-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 _CORE__INCLUDE__CORE_RM_SESSION_H_
|
||||||
|
#define _CORE__INCLUDE__CORE_RM_SESSION_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <rm_session/rm_session.h>
|
||||||
|
#include <base/rpc_server.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <dataspace_component.h>
|
||||||
|
|
||||||
|
namespace Genode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Region manager that uses the physical dataspace
|
||||||
|
* addresses directly as virtual addresses.
|
||||||
|
*/
|
||||||
|
class Core_rm_session : public Rm_session
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Rpc_entrypoint *_ds_ep;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Core_rm_session(Rpc_entrypoint *ds_ep): _ds_ep(ds_ep) { }
|
||||||
|
|
||||||
|
Local_addr attach(Dataspace_capability ds_cap, size_t size=0,
|
||||||
|
off_t offset=0, bool use_local_addr = false,
|
||||||
|
Local_addr local_addr = 0,
|
||||||
|
bool executable = false);
|
||||||
|
|
||||||
|
void detach(Local_addr) { }
|
||||||
|
|
||||||
|
Pager_capability add_client(Thread_capability thread) {
|
||||||
|
return Pager_capability(); }
|
||||||
|
|
||||||
|
void remove_client(Pager_capability) { }
|
||||||
|
|
||||||
|
void fault_handler(Signal_context_capability handler) { }
|
||||||
|
|
||||||
|
State state() { return State(); }
|
||||||
|
|
||||||
|
Dataspace_capability dataspace() { return Dataspace_capability(); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _CORE__INCLUDE__CORE_RM_SESSION_H_ */
|
46
base-hw/src/core/include/map_local.h
Normal file
46
base-hw/src/core/include/map_local.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* \brief Core-local mapping
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2014-02-26
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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__MAP_LOCAL_H_
|
||||||
|
#define _CORE__INCLUDE__MAP_LOCAL_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <base/printf.h>
|
||||||
|
|
||||||
|
namespace Genode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map physical pages to core-local virtual address range
|
||||||
|
*
|
||||||
|
* \param from_phys physical source address
|
||||||
|
* \param to_virt core-local destination address
|
||||||
|
* \param num_pages number of pages to map
|
||||||
|
* \param io_mem true if it's memory mapped I/O (uncached)
|
||||||
|
*
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool map_local(addr_t from_phys, addr_t to_virt, size_t num_pages,
|
||||||
|
bool io_mem = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmap pages from core's address space
|
||||||
|
*
|
||||||
|
* \param virt_addr first core-local address to unmap, must be page-aligned
|
||||||
|
* \param num_pages number of pages to unmap
|
||||||
|
*
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool unmap_local(addr_t virt_addr, size_t num_pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _CORE__INCLUDE__MAP_LOCAL_H_ */
|
230
base-hw/src/core/include/page_slab.h
Normal file
230
base-hw/src/core/include/page_slab.h
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
/*
|
||||||
|
* \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 <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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * operator new (size_t, void * p) { return p; }
|
||||||
|
};
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
size_t cnt = 0;
|
||||||
|
for (List_element<Slab_block> *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 = new (p) Slab_block();
|
||||||
|
_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; le = le->next()) {
|
||||||
|
if (!le->object()->free(addr)) continue;
|
||||||
|
|
||||||
|
if (_free_slab_entries++ > (MIN_SLABS+SLABS_PER_BLOCK)
|
||||||
|
&& !le->object()->ref_counter)
|
||||||
|
_free_slab_block(le->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) { return (*addr = alloc()); }
|
||||||
|
void free(void *addr, size_t) { free(addr); }
|
||||||
|
size_t consumed() { return SLAB_BLOCK_SIZE * _slab_blocks_in_use(); }
|
||||||
|
size_t overhead(size_t) { return SLAB_BLOCK_SIZE/SLABS_PER_BLOCK; }
|
||||||
|
bool need_size_for_free() const override { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _CORE__INCLUDE__PAGE_SLAB_H_ */
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Platform interface
|
* \brief Platform interface
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2011-12-21
|
* \date 2011-12-21
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -25,6 +26,8 @@
|
|||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <platform_generic.h>
|
#include <platform_generic.h>
|
||||||
|
#include <core_rm_session.h>
|
||||||
|
#include <core_mem_alloc.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
@ -33,16 +36,23 @@ namespace Genode {
|
|||||||
*/
|
*/
|
||||||
class Platform : public Platform_generic
|
class Platform : public Platform_generic
|
||||||
{
|
{
|
||||||
typedef Synchronized_range_allocator<Allocator_avl> Phys_allocator;
|
typedef Core_mem_allocator::Phys_allocator Phys_allocator;
|
||||||
|
|
||||||
Phys_allocator _core_mem_alloc; /* core-accessible memory */
|
Core_mem_allocator _core_mem_alloc; /* core-accessible memory */
|
||||||
Phys_allocator _io_mem_alloc; /* MMIO allocator */
|
Phys_allocator _io_mem_alloc; /* MMIO allocator */
|
||||||
Phys_allocator _io_port_alloc; /* I/O port allocator */
|
Phys_allocator _irq_alloc; /* IRQ allocator */
|
||||||
Phys_allocator _irq_alloc; /* IRQ allocator */
|
Rom_fs _rom_fs; /* ROM file system */
|
||||||
Rom_fs _rom_fs; /* ROM file system */
|
|
||||||
|
|
||||||
addr_t _vm_start; /* base of virtual address space */
|
/*
|
||||||
size_t _vm_size; /* size of virtual address space */
|
* Virtual-memory range for non-core address spaces.
|
||||||
|
* The virtual memory layout of core is maintained in
|
||||||
|
* '_core_mem_alloc.virt_alloc()'.
|
||||||
|
*/
|
||||||
|
addr_t _vm_start;
|
||||||
|
size_t _vm_size;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get one of the consecutively numbered available resource regions
|
* Get one of the consecutively numbered available resource regions
|
||||||
@ -79,8 +89,6 @@ namespace Genode {
|
|||||||
*/
|
*/
|
||||||
static unsigned * _irq(unsigned const i);
|
static unsigned * _irq(unsigned const i);
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
@ -91,13 +99,18 @@ namespace Genode {
|
|||||||
** Platform_generic interface **
|
** Platform_generic interface **
|
||||||
********************************/
|
********************************/
|
||||||
|
|
||||||
inline Range_allocator * core_mem_alloc() { return &_core_mem_alloc; }
|
inline Range_allocator * core_mem_alloc() {
|
||||||
|
return &_core_mem_alloc; }
|
||||||
|
|
||||||
inline Range_allocator * ram_alloc() { return &_core_mem_alloc; }
|
inline Range_allocator * ram_alloc() {
|
||||||
|
return _core_mem_alloc.phys_alloc(); }
|
||||||
|
|
||||||
|
inline Range_allocator * region_alloc() {
|
||||||
|
return _core_mem_alloc.virt_alloc(); }
|
||||||
|
|
||||||
inline Range_allocator * io_mem_alloc() { return &_io_mem_alloc; }
|
inline Range_allocator * io_mem_alloc() { return &_io_mem_alloc; }
|
||||||
|
|
||||||
inline Range_allocator * io_port_alloc() { return &_io_port_alloc; }
|
inline Range_allocator * io_port_alloc() { return 0; }
|
||||||
|
|
||||||
inline Range_allocator * irq_alloc() { return &_irq_alloc; }
|
inline Range_allocator * irq_alloc() { return &_irq_alloc; }
|
||||||
|
|
||||||
@ -114,13 +127,6 @@ namespace Genode {
|
|||||||
|
|
||||||
bool supports_direct_unmap() const { return 1; }
|
bool supports_direct_unmap() const { return 1; }
|
||||||
|
|
||||||
inline Range_allocator * region_alloc()
|
|
||||||
{
|
|
||||||
Kernel::log() << __PRETTY_FUNCTION__ << "not implemented\n";
|
|
||||||
while (1) ;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Affinity::Space affinity_space() const
|
Affinity::Space affinity_space() const
|
||||||
{
|
{
|
||||||
return Affinity::Space(PROCESSORS);
|
return Affinity::Space(PROCESSORS);
|
||||||
|
@ -20,25 +20,15 @@
|
|||||||
#include <root/root.h>
|
#include <root/root.h>
|
||||||
|
|
||||||
/* Core includes */
|
/* Core includes */
|
||||||
#include <tlb.h>
|
#include <translation_table.h>
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
#include <address_space.h>
|
#include <address_space.h>
|
||||||
|
#include <page_slab.h>
|
||||||
|
#include <kernel/kernel.h>
|
||||||
|
|
||||||
namespace Genode
|
namespace Genode
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Regain all administrative memory that isn't used anymore by 'tlb'
|
|
||||||
*/
|
|
||||||
inline void regain_ram_from_tlb(Tlb * tlb)
|
|
||||||
{
|
|
||||||
size_t s;
|
|
||||||
void * base;
|
|
||||||
while (tlb->regain_memory(base, s)) {
|
|
||||||
platform()->ram_alloc()->free(base, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Platform_thread;
|
class Platform_thread;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,42 +38,59 @@ namespace Genode
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
unsigned _id;
|
Lock _lock; /* safeguard translation table and slab */
|
||||||
Native_capability _parent;
|
unsigned _id;
|
||||||
Native_thread_id _main_thread;
|
Native_capability _parent;
|
||||||
char const * const _label;
|
Native_thread_id _main_thread;
|
||||||
Tlb * _tlb;
|
char const * const _label;
|
||||||
|
Translation_table * _tt; /* translation table virtual addr. */
|
||||||
|
Translation_table * _tt_phys; /* translation table physical addr. */
|
||||||
|
uint8_t _kernel_pd[sizeof(Kernel::Pd)];
|
||||||
|
Page_slab * _pslab; /* page table allocator */
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for core pd
|
* Constructor for core pd
|
||||||
|
*
|
||||||
|
* \param tt translation table address
|
||||||
|
* \param slab page table allocator
|
||||||
*/
|
*/
|
||||||
Platform_pd(Tlb * tlb)
|
Platform_pd(Translation_table * tt, Page_slab * slab)
|
||||||
: _main_thread(0), _label("core"), _tlb(tlb) { }
|
: _main_thread(0), _label("core"), _tt(tt),
|
||||||
|
_tt_phys(tt), _pslab(slab) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor for non-core pd
|
||||||
|
*
|
||||||
|
* \param label name of protection domain
|
||||||
*/
|
*/
|
||||||
Platform_pd(char const *label) : _main_thread(0), _label(label)
|
Platform_pd(char const *label) : _main_thread(0), _label(label)
|
||||||
{
|
{
|
||||||
/* get some aligned space for the kernel object */
|
Lock::Guard guard(_lock);
|
||||||
void * kernel_pd = 0;
|
|
||||||
Range_allocator * ram = platform()->ram_alloc();
|
Core_mem_allocator * cma =
|
||||||
bool kernel_pd_ok =
|
static_cast<Core_mem_allocator*>(platform()->core_mem_alloc());
|
||||||
ram->alloc_aligned(Kernel::pd_size(), &kernel_pd,
|
void *tt;
|
||||||
Kernel::pd_alignment_log2()).is_ok();
|
|
||||||
if (!kernel_pd_ok) {
|
/* get some aligned space for the translation table */
|
||||||
|
if (!cma->alloc_aligned(sizeof(Translation_table), (void**)&tt,
|
||||||
|
Translation_table::ALIGNM_LOG2).is_ok()) {
|
||||||
PERR("failed to allocate kernel object");
|
PERR("failed to allocate kernel object");
|
||||||
throw Root::Quota_exceeded();
|
throw Root::Quota_exceeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_tt = new (tt) Translation_table();
|
||||||
|
_tt_phys = (Translation_table*) cma->phys_addr(_tt);
|
||||||
|
_pslab = new (cma) Page_slab(cma);
|
||||||
|
Kernel::mtc()->map(_tt, _pslab);
|
||||||
|
|
||||||
/* create kernel object */
|
/* create kernel object */
|
||||||
_id = Kernel::new_pd(kernel_pd, this);
|
_id = Kernel::new_pd(&_kernel_pd, this);
|
||||||
if (!_id) {
|
if (!_id) {
|
||||||
PERR("failed to create kernel object");
|
PERR("failed to create kernel object");
|
||||||
throw Root::Unavailable();
|
throw Root::Unavailable();
|
||||||
}
|
}
|
||||||
_tlb = (Tlb *)kernel_pd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -109,6 +116,14 @@ namespace Genode
|
|||||||
return t->join_pd(this, 0, Address_space::weak_ptr());
|
return t->join_pd(this, 0, Address_space::weak_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbind thread 't' from protection domain
|
||||||
|
*/
|
||||||
|
void unbind_thread(Platform_thread *t) {
|
||||||
|
t->join_pd(nullptr, false, Address_space::weak_ptr()); }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign parent interface to protection domain
|
* Assign parent interface to protection domain
|
||||||
*/
|
*/
|
||||||
@ -127,8 +142,13 @@ namespace Genode
|
|||||||
** Accessors **
|
** Accessors **
|
||||||
***************/
|
***************/
|
||||||
|
|
||||||
unsigned const id() { return _id; }
|
Lock * lock() { return &_lock; }
|
||||||
char const * const label() { return _label; }
|
unsigned const id() { return _id; }
|
||||||
|
char const * const label() { return _label; }
|
||||||
|
Page_slab * page_slab() { return _pslab; }
|
||||||
|
Translation_table * translation_table() { return _tt; }
|
||||||
|
Translation_table * translation_table_phys() { return _tt_phys; }
|
||||||
|
void page_slab(Page_slab *pslab) { _pslab = pslab; }
|
||||||
|
|
||||||
|
|
||||||
/*****************************
|
/*****************************
|
||||||
|
@ -34,6 +34,7 @@ namespace Genode {
|
|||||||
class Thread_state;
|
class Thread_state;
|
||||||
class Rm_client;
|
class Rm_client;
|
||||||
class Platform_thread;
|
class Platform_thread;
|
||||||
|
class Platform_pd;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Userland interface for the management of kernel thread-objects
|
* Userland interface for the management of kernel thread-objects
|
||||||
@ -42,15 +43,13 @@ namespace Genode {
|
|||||||
{
|
{
|
||||||
enum { LABEL_MAX_LEN = 32 };
|
enum { LABEL_MAX_LEN = 32 };
|
||||||
|
|
||||||
size_t _stack_size;
|
|
||||||
Platform_pd * _pd;
|
Platform_pd * _pd;
|
||||||
Weak_ptr<Address_space> _address_space;
|
Weak_ptr<Address_space> _address_space;
|
||||||
unsigned _id;
|
unsigned _id;
|
||||||
Rm_client * _rm_client;
|
Rm_client * _rm_client;
|
||||||
Native_utcb * _utcb_phys;
|
Native_utcb * _utcb_core_addr; /* UTCB address in core */
|
||||||
Native_utcb * _utcb_virt;
|
Native_utcb * _utcb_pd_addr; /* UTCB address in pd */
|
||||||
Tlb * _tlb;
|
Ram_dataspace_capability _utcb; /* UTCB dataspace */
|
||||||
Ram_dataspace_capability _utcb;
|
|
||||||
char _label[LABEL_MAX_LEN];
|
char _label[LABEL_MAX_LEN];
|
||||||
char _kernel_thread[sizeof(Kernel::Thread)];
|
char _kernel_thread[sizeof(Kernel::Thread)];
|
||||||
|
|
||||||
@ -81,10 +80,10 @@ namespace Genode {
|
|||||||
/**
|
/**
|
||||||
* Constructor for core threads
|
* Constructor for core threads
|
||||||
*
|
*
|
||||||
* \param stack_size initial size of the stack
|
|
||||||
* \param label debugging label
|
* \param label debugging label
|
||||||
|
* \param utcb virtual address of UTCB within core
|
||||||
*/
|
*/
|
||||||
Platform_thread(size_t const stack_size, const char * const label);
|
Platform_thread(const char * const label, Native_utcb * utcb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for threads outside of core
|
* Constructor for threads outside of core
|
||||||
@ -182,13 +181,7 @@ namespace Genode {
|
|||||||
|
|
||||||
Native_thread_id id() const { return _id; }
|
Native_thread_id id() const { return _id; }
|
||||||
|
|
||||||
size_t stack_size() const { return _stack_size; }
|
|
||||||
|
|
||||||
Native_utcb * utcb_virt() const { return _utcb_virt; }
|
|
||||||
|
|
||||||
Ram_dataspace_capability utcb() const { return _utcb; }
|
Ram_dataspace_capability utcb() const { return _utcb; }
|
||||||
|
|
||||||
Tlb * tlb() const { return _tlb; }
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,19 +30,23 @@
|
|||||||
#include <trustzone.h>
|
#include <trustzone.h>
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
#include <pic.h>
|
#include <pic.h>
|
||||||
|
#include <map_local.h>
|
||||||
|
|
||||||
/* base includes */
|
/* base includes */
|
||||||
|
#include <base/allocator_avl.h>
|
||||||
#include <unmanaged_singleton.h>
|
#include <unmanaged_singleton.h>
|
||||||
|
#include <base/native_types.h>
|
||||||
|
|
||||||
/* base-hw includes */
|
/* base-hw includes */
|
||||||
#include <kernel/irq.h>
|
#include <kernel/irq.h>
|
||||||
#include <kernel/perf_counter.h>
|
#include <kernel/perf_counter.h>
|
||||||
|
|
||||||
using namespace Kernel;
|
using namespace Kernel;
|
||||||
|
|
||||||
extern Genode::Native_thread_id _main_thread_id;
|
extern Genode::Native_thread_id _main_thread_id;
|
||||||
extern "C" void CORE_MAIN();
|
extern "C" void CORE_MAIN();
|
||||||
extern void * _start_secondary_processors;
|
extern void * _start_secondary_processors;
|
||||||
|
extern int _prog_img_beg;
|
||||||
|
extern int _prog_img_end;
|
||||||
|
|
||||||
Genode::Native_utcb * _main_thread_utcb;
|
Genode::Native_utcb * _main_thread_utcb;
|
||||||
|
|
||||||
@ -55,7 +59,6 @@ namespace Kernel
|
|||||||
|
|
||||||
/* import Genode types */
|
/* import Genode types */
|
||||||
typedef Genode::umword_t umword_t;
|
typedef Genode::umword_t umword_t;
|
||||||
typedef Genode::Core_tlb Core_tlb;
|
|
||||||
typedef Genode::Core_thread_id Core_thread_id;
|
typedef Genode::Core_thread_id Core_thread_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,24 +98,65 @@ namespace Kernel
|
|||||||
*/
|
*/
|
||||||
Pd * core_pd()
|
Pd * core_pd()
|
||||||
{
|
{
|
||||||
|
using Ttable = Genode::Translation_table;
|
||||||
|
constexpr int tt_align = 1 << Ttable::ALIGNM_LOG2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Core protection-domain
|
* Dummy page slab backend allocator for bootstrapping only
|
||||||
*/
|
*/
|
||||||
struct Core_pd : public Platform_pd, public Pd
|
struct Simple_allocator : Genode::Core_mem_translator
|
||||||
{
|
{
|
||||||
/**
|
Simple_allocator() { }
|
||||||
* Constructor
|
|
||||||
*/
|
int add_range(addr_t base, size_t size) { return -1; }
|
||||||
Core_pd(Tlb * const tlb)
|
int remove_range(addr_t base, size_t size) { return -1; }
|
||||||
: Platform_pd(tlb),
|
Alloc_return alloc_aligned(size_t size, void **out_addr, int align) {
|
||||||
Pd(tlb, this)
|
return Alloc_return::RANGE_CONFLICT; }
|
||||||
|
Alloc_return alloc_addr(size_t size, addr_t addr) {
|
||||||
|
return Alloc_return::RANGE_CONFLICT; }
|
||||||
|
void free(void *addr) {}
|
||||||
|
size_t avail() { return 0; }
|
||||||
|
bool valid_addr(addr_t addr) { return false; }
|
||||||
|
bool alloc(size_t size, void **out_addr) { return false; }
|
||||||
|
void free(void *addr, size_t) { }
|
||||||
|
size_t overhead(size_t size) { 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; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Core_pd : Platform_pd, Pd
|
||||||
|
{
|
||||||
|
Core_pd(Ttable * tt, Genode::Page_slab * slab)
|
||||||
|
: Platform_pd(tt, slab),
|
||||||
|
Pd(tt, this)
|
||||||
{
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
Platform_pd::_id = Pd::id();
|
Platform_pd::_id = Pd::id();
|
||||||
|
|
||||||
|
/* map exception vector for core */
|
||||||
|
Kernel::mtc()->map(tt, slab);
|
||||||
|
|
||||||
|
/* map core's program image */
|
||||||
|
addr_t start = trunc_page((addr_t)&_prog_img_beg);
|
||||||
|
addr_t end = round_page((addr_t)&_prog_img_end);
|
||||||
|
map_local(start, start, (end-start) / get_page_size());
|
||||||
|
|
||||||
|
/* map core's mmio regions */
|
||||||
|
Native_region * r = Platform::_core_only_mmio_regions(0);
|
||||||
|
for (unsigned i = 0; r;
|
||||||
|
r = Platform::_core_only_mmio_regions(++i))
|
||||||
|
map_local(r->base, r->base, r->size / get_page_size(), true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
constexpr int tlb_align = 1 << Core_tlb::ALIGNM_LOG2;
|
|
||||||
Core_tlb * core_tlb = unmanaged_singleton<Core_tlb, tlb_align>();
|
Simple_allocator * sa = unmanaged_singleton<Simple_allocator>();
|
||||||
return unmanaged_singleton<Core_pd>(core_tlb);
|
Ttable * tt = unmanaged_singleton<Ttable, tt_align>();
|
||||||
|
Genode::Page_slab * slab = unmanaged_singleton<Genode::Page_slab,
|
||||||
|
tt_align>(sa);
|
||||||
|
return unmanaged_singleton<Core_pd>(tt, slab);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -142,12 +186,12 @@ namespace Kernel
|
|||||||
/**
|
/**
|
||||||
* Get attributes of the kernel objects
|
* Get attributes of the kernel objects
|
||||||
*/
|
*/
|
||||||
size_t thread_size() { return sizeof(Thread); }
|
size_t thread_size() { return sizeof(Thread); }
|
||||||
size_t pd_size() { return sizeof(Tlb) + sizeof(Pd); }
|
size_t signal_context_size() { return sizeof(Signal_context); }
|
||||||
size_t signal_context_size() { return sizeof(Signal_context); }
|
size_t signal_receiver_size() { return sizeof(Signal_receiver); }
|
||||||
size_t signal_receiver_size() { return sizeof(Signal_receiver); }
|
size_t vm_size() { return sizeof(Vm); }
|
||||||
unsigned pd_alignment_log2() { return Tlb::ALIGNM_LOG2; }
|
unsigned pd_alignm_log2() { return Genode::Translation_table::ALIGNM_LOG2; }
|
||||||
size_t vm_size() { return sizeof(Vm); }
|
size_t pd_size() { return sizeof(Genode::Translation_table) + sizeof(Pd); }
|
||||||
|
|
||||||
enum { STACK_SIZE = 64 * 1024 };
|
enum { STACK_SIZE = 64 * 1024 };
|
||||||
|
|
||||||
@ -160,7 +204,7 @@ namespace Kernel
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_t core_tlb_base;
|
addr_t core_tt_base;
|
||||||
unsigned core_pd_id;
|
unsigned core_pd_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,8 +228,8 @@ extern "C" void init_kernel_uniprocessor()
|
|||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
/* calculate in advance as needed later when data writes aren't allowed */
|
/* calculate in advance as needed later when data writes aren't allowed */
|
||||||
core_tlb_base = core_pd()->tlb()->base();
|
core_tt_base = (addr_t) core_pd()->translation_table();
|
||||||
core_pd_id = core_pd()->id();
|
core_pd_id = core_pd()->id();
|
||||||
|
|
||||||
/* initialize all processor objects */
|
/* initialize all processor objects */
|
||||||
processor_pool();
|
processor_pool();
|
||||||
@ -216,7 +260,7 @@ extern "C" void init_kernel_multiprocessor()
|
|||||||
Processor::init_phys_kernel();
|
Processor::init_phys_kernel();
|
||||||
|
|
||||||
/* switch to core address space */
|
/* switch to core address space */
|
||||||
Processor::init_virt_kernel(core_tlb_base, core_pd_id);
|
Processor::init_virt_kernel(core_tt_base, core_pd_id);
|
||||||
|
|
||||||
/************************************
|
/************************************
|
||||||
** Now it's safe to use 'cmpxchg' **
|
** Now it's safe to use 'cmpxchg' **
|
||||||
@ -307,9 +351,6 @@ extern "C" void kernel()
|
|||||||
Processor_client * const old_occupant = scheduler->occupant();
|
Processor_client * const old_occupant = scheduler->occupant();
|
||||||
old_occupant->exception(processor_id);
|
old_occupant->exception(processor_id);
|
||||||
|
|
||||||
/* check for TLB maintainance requirements */
|
|
||||||
processor->flush_tlb();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The processor local as well as remote exception-handling may have
|
* The processor local as well as remote exception-handling may have
|
||||||
* changed the scheduling of the local activities. Hence we must update the
|
* changed the scheduling of the local activities. Hence we must update the
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
#include <kernel/pd.h>
|
#include <kernel/pd.h>
|
||||||
|
|
||||||
namespace Kernel { Pd * core_pd(); }
|
namespace Kernel {
|
||||||
|
Pd * core_pd();
|
||||||
|
Mode_transition_control * mtc();
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _KERNEL__KERNEL_H_ */
|
#endif /* _KERNEL__KERNEL_H_ */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Kernel backend for protection domains
|
* \brief Kernel backend for protection domains
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-11-30
|
* \date 2012-11-30
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -21,8 +22,9 @@
|
|||||||
#include <kernel/configuration.h>
|
#include <kernel/configuration.h>
|
||||||
#include <kernel/object.h>
|
#include <kernel/object.h>
|
||||||
#include <kernel/processor.h>
|
#include <kernel/processor.h>
|
||||||
#include <tlb.h>
|
#include <translation_table.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <page_slab.h>
|
||||||
|
|
||||||
/* structure of the mode transition */
|
/* structure of the mode transition */
|
||||||
extern int _mt_begin;
|
extern int _mt_begin;
|
||||||
@ -148,7 +150,7 @@ class Kernel::Mode_transition_control
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SIZE_LOG2 = Tlb::MIN_PAGE_SIZE_LOG2,
|
SIZE_LOG2 = Genode::Translation_table::MIN_PAGE_SIZE_LOG2,
|
||||||
SIZE = 1 << SIZE_LOG2,
|
SIZE = 1 << SIZE_LOG2,
|
||||||
VIRT_BASE = Processor::EXCEPTION_ENTRY,
|
VIRT_BASE = Processor::EXCEPTION_ENTRY,
|
||||||
VIRT_END = VIRT_BASE + SIZE,
|
VIRT_END = VIRT_BASE + SIZE,
|
||||||
@ -185,17 +187,18 @@ 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 tlb translation buffer of the address space
|
* \param tt translation buffer of the address space
|
||||||
* \param ram RAM donation for mapping (first try without)
|
* \param ram RAM donation for mapping (first try without)
|
||||||
*
|
|
||||||
* \return RAM-donation size that is needed to do the mapping
|
|
||||||
*/
|
*/
|
||||||
size_t map(Tlb * tlb, addr_t ram = 0)
|
void map(Genode::Translation_table * tt,
|
||||||
|
Genode::Page_slab * alloc)
|
||||||
{
|
{
|
||||||
addr_t const phys_base = (addr_t)&_mt_begin;
|
try {
|
||||||
return tlb->insert_translation(VIRT_BASE, phys_base, SIZE_LOG2,
|
addr_t const phys_base = (addr_t)&_mt_begin;
|
||||||
Page_flags::mode_transition(),
|
tt->insert_translation(VIRT_BASE, phys_base, SIZE,
|
||||||
(void *)ram);
|
Page_flags::mode_transition(), alloc);
|
||||||
|
} catch(...) {
|
||||||
|
PERR("Inserting exception vector in page table failed!"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -227,11 +230,14 @@ class Kernel::Pd : public Object<Pd, MAX_PDS, Pd_ids, pd_ids, pd_pool>
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Tlb * const _tlb;
|
Genode::Translation_table * const _tt;
|
||||||
Platform_pd * const _platform_pd;
|
Platform_pd * const _platform_pd;
|
||||||
|
|
||||||
/* keep ready memory for size-aligned extra costs at construction */
|
/* keep ready memory for size-aligned extra costs at construction */
|
||||||
enum { EXTRA_RAM_SIZE = 2 * Tlb::MAX_COSTS_PER_TRANSLATION };
|
enum {
|
||||||
|
EXTRA_RAM_SIZE = 2 * Genode::Translation_table::MAX_COSTS_PER_TRANSLATION
|
||||||
|
};
|
||||||
|
|
||||||
char _extra_ram[EXTRA_RAM_SIZE];
|
char _extra_ram[EXTRA_RAM_SIZE];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -239,33 +245,12 @@ class Kernel::Pd : public Object<Pd, MAX_PDS, Pd_ids, pd_ids, pd_pool>
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* \param tlb translation lookaside buffer of the PD
|
* \param tt translation lookaside buffer of the PD
|
||||||
* \param platform_pd core object of the PD
|
* \param platform_pd core object of the PD
|
||||||
*/
|
*/
|
||||||
Pd(Tlb * const tlb, Platform_pd * const platform_pd)
|
Pd(Genode::Translation_table * const tt,
|
||||||
:
|
Platform_pd * const platform_pd)
|
||||||
_tlb(tlb), _platform_pd(platform_pd)
|
: _tt(tt), _platform_pd(platform_pd) { }
|
||||||
{
|
|
||||||
/* try to add translation for mode transition region */
|
|
||||||
unsigned const slog2 = mtc()->map(tlb);
|
|
||||||
|
|
||||||
/* extra ram needed to translate mode transition region */
|
|
||||||
if (slog2)
|
|
||||||
{
|
|
||||||
/* get size aligned extra ram */
|
|
||||||
addr_t const ram = (addr_t)&_extra_ram;
|
|
||||||
addr_t const ram_end = ram + sizeof(_extra_ram);
|
|
||||||
addr_t const aligned_ram = (ram_end - (1 << slog2)) &
|
|
||||||
~((1 << slog2) - 1);
|
|
||||||
addr_t const aligned_ram_end = aligned_ram + (1 << slog2);
|
|
||||||
|
|
||||||
/* check attributes of aligned extra ram */
|
|
||||||
assert(aligned_ram >= ram && aligned_ram_end <= ram_end)
|
|
||||||
|
|
||||||
/* translate mode transition region globally */
|
|
||||||
mtc()->map(tlb, aligned_ram);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor
|
* Destructor
|
||||||
@ -278,7 +263,7 @@ class Kernel::Pd : public Object<Pd, MAX_PDS, Pd_ids, pd_ids, pd_pool>
|
|||||||
void admit(Processor::Context * const c)
|
void admit(Processor::Context * const c)
|
||||||
{
|
{
|
||||||
c->protection_domain(id());
|
c->protection_domain(id());
|
||||||
c->tlb(tlb()->base());
|
c->translation_table((addr_t)translation_table());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -286,9 +271,10 @@ class Kernel::Pd : public Object<Pd, MAX_PDS, Pd_ids, pd_ids, pd_pool>
|
|||||||
** Accessors **
|
** Accessors **
|
||||||
***************/
|
***************/
|
||||||
|
|
||||||
Tlb * tlb() const { return _tlb; }
|
|
||||||
|
|
||||||
Platform_pd * platform_pd() const { return _platform_pd; }
|
Platform_pd * platform_pd() const { return _platform_pd; }
|
||||||
|
|
||||||
|
Genode::Translation_table * translation_table() const {
|
||||||
|
return _tt; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _KERNEL__PD_H_ */
|
#endif /* _KERNEL__PD_H_ */
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <kernel/processor.h>
|
#include <kernel/processor.h>
|
||||||
|
#include <kernel/processor_pool.h>
|
||||||
#include <kernel/thread.h>
|
#include <kernel/thread.h>
|
||||||
#include <kernel/irq.h>
|
#include <kernel/irq.h>
|
||||||
#include <pic.h>
|
#include <pic.h>
|
||||||
@ -27,6 +28,16 @@ namespace Kernel
|
|||||||
Timer * timer();
|
Timer * timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using Tlb_list_item = Genode::List_element<Processor_client>;
|
||||||
|
using Tlb_list = Genode::List<Tlb_list_item>;
|
||||||
|
|
||||||
|
|
||||||
|
static Tlb_list *tlb_list()
|
||||||
|
{
|
||||||
|
static Tlb_list tlb_list;
|
||||||
|
return &tlb_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Kernel::Processor_client::_interrupt(unsigned const processor_id)
|
void Kernel::Processor_client::_interrupt(unsigned const processor_id)
|
||||||
{
|
{
|
||||||
@ -63,20 +74,40 @@ void Kernel::Processor_client::_schedule() { __processor->schedule(this); }
|
|||||||
|
|
||||||
void Kernel::Processor_client::tlb_to_flush(unsigned pd_id)
|
void Kernel::Processor_client::tlb_to_flush(unsigned pd_id)
|
||||||
{
|
{
|
||||||
/* initialize pd and reference counter, and remove client from scheduler */
|
/* initialize pd and reference counters, and remove client from scheduler */
|
||||||
_flush_tlb_pd_id = pd_id;
|
_flush_tlb_pd_id = pd_id;
|
||||||
_flush_tlb_ref_cnt = PROCESSORS;
|
for (unsigned i = 0; i < PROCESSORS; i++)
|
||||||
|
_flush_tlb_ref_cnt[i] = false;
|
||||||
_unschedule();
|
_unschedule();
|
||||||
|
|
||||||
|
/* find the last working item in the TLB work queue */
|
||||||
|
Tlb_list_item * last = tlb_list()->first();
|
||||||
|
while (last && last->next()) last = last->next();
|
||||||
|
|
||||||
|
/* insert new work item at the end of the work list */
|
||||||
|
tlb_list()->insert(&_flush_tlb_li, last);
|
||||||
|
|
||||||
|
/* enforce kernel entry of other processors */
|
||||||
|
for (unsigned i = 0; i < PROCESSORS; i++)
|
||||||
|
pic()->trigger_ip_interrupt(i);
|
||||||
|
|
||||||
|
processor_pool()->processor(Processor::executing_id())->flush_tlb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Kernel::Processor_client::flush_tlb_by_id()
|
void Kernel::Processor_client::flush_tlb_by_id()
|
||||||
{
|
{
|
||||||
|
/* flush TLB on current processor and adjust ref counter */
|
||||||
Processor::flush_tlb_by_pid(_flush_tlb_pd_id);
|
Processor::flush_tlb_by_pid(_flush_tlb_pd_id);
|
||||||
|
_flush_tlb_ref_cnt[Processor::executing_id()] = true;
|
||||||
|
|
||||||
/* if reference counter reaches zero, add client to scheduler again */
|
/* check whether all processors are done */
|
||||||
if (--_flush_tlb_ref_cnt == 0)
|
for (unsigned i = 0; i < PROCESSORS; i++)
|
||||||
_schedule();
|
if (!_flush_tlb_ref_cnt[i]) return;
|
||||||
|
|
||||||
|
/* remove work item from the list and re-schedule thread */
|
||||||
|
tlb_list()->remove(&_flush_tlb_li);
|
||||||
|
_schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -122,26 +153,12 @@ void Kernel::Processor_client::_yield()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Kernel::Processor::flush_tlb(Processor_client * const client)
|
|
||||||
{
|
|
||||||
/* find the last working item in the TLB work queue */
|
|
||||||
Genode::List_element<Processor_client> * last = _ipi_scheduler.first();
|
|
||||||
while (last && last->next()) last = last->next();
|
|
||||||
|
|
||||||
/* insert new work item at the end of the work list */
|
|
||||||
_ipi_scheduler.insert(&client->_flush_tlb_li, last);
|
|
||||||
|
|
||||||
/* enforce kernel entry of the corresponding processor */
|
|
||||||
pic()->trigger_ip_interrupt(_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Kernel::Processor::flush_tlb()
|
void Kernel::Processor::flush_tlb()
|
||||||
{
|
{
|
||||||
/* iterate through the list of TLB work items, and proceed them */
|
/* iterate through the list of TLB work items, and proceed them */
|
||||||
for (Genode::List_element<Processor_client> * cli = _ipi_scheduler.first(); cli;
|
for (Tlb_list_item * cli = tlb_list()->first(); cli;) {
|
||||||
cli = _ipi_scheduler.first()) {
|
Tlb_list_item * current = cli;
|
||||||
cli->object()->flush_tlb_by_id();
|
cli = current->next();
|
||||||
_ipi_scheduler.remove(cli);
|
current->object()->flush_tlb_by_id();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,7 @@ class Kernel::Processor_client : public Processor_scheduler::Item
|
|||||||
|
|
||||||
List_item _flush_tlb_li; /* TLB maintainance work list item */
|
List_item _flush_tlb_li; /* TLB maintainance work list item */
|
||||||
unsigned _flush_tlb_pd_id; /* id of pd that TLB entries are flushed */
|
unsigned _flush_tlb_pd_id; /* id of pd that TLB entries are flushed */
|
||||||
unsigned _flush_tlb_ref_cnt; /* reference counter */
|
bool _flush_tlb_ref_cnt[PROCESSORS]; /* reference counters */
|
||||||
|
|
||||||
friend class Processor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle an interrupt exception that occured during execution
|
* Handle an interrupt exception that occured during execution
|
||||||
@ -104,7 +102,7 @@ class Kernel::Processor_client : public Processor_scheduler::Item
|
|||||||
virtual void proceed(unsigned const processor_id) = 0;
|
virtual void proceed(unsigned const processor_id) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the pd id, which TLB entries should be flushed
|
* Enqueues TLB maintainance work into queue of the processors
|
||||||
*
|
*
|
||||||
* \param pd_id protection domain kernel object's id
|
* \param pd_id protection domain kernel object's id
|
||||||
*/
|
*/
|
||||||
@ -142,11 +140,8 @@ class Kernel::Processor : public Processor_driver
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
using Ipi_scheduler = Genode::List<Genode::List_element<Processor_client> >;
|
|
||||||
|
|
||||||
unsigned const _id;
|
unsigned const _id;
|
||||||
Processor_scheduler _scheduler;
|
Processor_scheduler _scheduler;
|
||||||
Ipi_scheduler _ipi_scheduler;
|
|
||||||
bool _ip_interrupt_pending;
|
bool _ip_interrupt_pending;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -162,6 +157,11 @@ class Kernel::Processor : public Processor_driver
|
|||||||
_id(id), _scheduler(idle_client), _ip_interrupt_pending(false)
|
_id(id), _scheduler(idle_client), _ip_interrupt_pending(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform outstanding TLB maintainance work
|
||||||
|
*/
|
||||||
|
void flush_tlb();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notice that the inter-processor interrupt isn't pending anymore
|
* Notice that the inter-processor interrupt isn't pending anymore
|
||||||
*/
|
*/
|
||||||
@ -174,6 +174,7 @@ class Kernel::Processor : public Processor_driver
|
|||||||
* available.
|
* available.
|
||||||
*/
|
*/
|
||||||
_ip_interrupt_pending = false;
|
_ip_interrupt_pending = false;
|
||||||
|
flush_tlb();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -184,19 +185,6 @@ class Kernel::Processor : public Processor_driver
|
|||||||
void schedule(Processor_client * const client);
|
void schedule(Processor_client * const client);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add processor client to the TLB maintainance queue of the processor
|
|
||||||
*
|
|
||||||
* \param client targeted client
|
|
||||||
*/
|
|
||||||
void flush_tlb(Processor_client * const client);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform outstanding TLB maintainance work
|
|
||||||
*/
|
|
||||||
void flush_tlb();
|
|
||||||
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
** Accessors **
|
** Accessors **
|
||||||
***************/
|
***************/
|
||||||
|
@ -172,8 +172,7 @@ void Thread::init(Processor * const processor, Pd * const pd,
|
|||||||
|
|
||||||
/* join protection domain */
|
/* join protection domain */
|
||||||
_pd = pd;
|
_pd = pd;
|
||||||
addr_t const tlb = _pd->tlb()->base();
|
User_context::init_thread((addr_t)_pd->translation_table(), pd_id());
|
||||||
User_context::init_thread(tlb, pd_id());
|
|
||||||
|
|
||||||
/* print log message */
|
/* print log message */
|
||||||
if (START_VERBOSE) {
|
if (START_VERBOSE) {
|
||||||
@ -243,11 +242,13 @@ char const * Kernel::Thread::pd_label() const
|
|||||||
|
|
||||||
void Thread::_call_new_pd()
|
void Thread::_call_new_pd()
|
||||||
{
|
{
|
||||||
/* create translation lookaside buffer and protection domain */
|
using namespace Genode;
|
||||||
void * p = (void *)user_arg_1();
|
|
||||||
Tlb * const tlb = new (p) Tlb();
|
/* create protection domain */
|
||||||
p = (void *)((addr_t)p + sizeof(Tlb));
|
void * p = (void *) user_arg_1();
|
||||||
Pd * const pd = new (p) Pd(tlb, (Platform_pd *)user_arg_2());
|
Platform_pd * ppd = (Platform_pd *) user_arg_2();
|
||||||
|
Translation_table * tt = ppd->translation_table_phys();
|
||||||
|
Pd * const pd = new (p) Pd(tt, ppd);
|
||||||
user_arg_0(pd->id());
|
user_arg_0(pd->id());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,10 +263,8 @@ void Thread::_call_bin_pd()
|
|||||||
user_arg_0(-1);
|
user_arg_0(-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* destruct translation lookaside buffer and protection domain */
|
/* destruct protection domain */
|
||||||
Tlb * const tlb = pd->tlb();
|
|
||||||
pd->~Pd();
|
pd->~Pd();
|
||||||
tlb->~Tlb();
|
|
||||||
|
|
||||||
/* clean up buffers of memory management */
|
/* clean up buffers of memory management */
|
||||||
Processor::flush_tlb_by_pid(pd->id());
|
Processor::flush_tlb_by_pid(pd->id());
|
||||||
@ -326,7 +325,7 @@ void Thread::_call_start_thread()
|
|||||||
/* start thread */
|
/* start thread */
|
||||||
Native_utcb * const utcb = (Native_utcb *)user_arg_4();
|
Native_utcb * const utcb = (Native_utcb *)user_arg_4();
|
||||||
thread->init(processor, pd, utcb, 1);
|
thread->init(processor, pd, utcb, 1);
|
||||||
user_arg_0((Call_ret)thread->_pd->tlb());
|
user_arg_0((Call_ret)thread->_pd->translation_table());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -538,10 +537,6 @@ void Thread::_call_access_thread_regs()
|
|||||||
void Thread::_call_update_pd()
|
void Thread::_call_update_pd()
|
||||||
{
|
{
|
||||||
tlb_to_flush(user_arg_1());
|
tlb_to_flush(user_arg_1());
|
||||||
|
|
||||||
/* inform other processors */
|
|
||||||
for (unsigned i = 0; i < PROCESSORS; i++)
|
|
||||||
Kernel::processor_pool()->processor(i)->flush_tlb(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Transtaltion lookaside buffer
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2012-04-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _PANDA__TLB_H_
|
|
||||||
#define _PANDA__TLB_H_
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <board.h>
|
|
||||||
#include <tlb/arm_v7.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
class Tlb : public Arm_v7::Section_table { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transtaltion lookaside buffer of core
|
|
||||||
*/
|
|
||||||
class Core_tlb : public Tlb
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* On Pandaboard the L2 cache needs to be disabled by a
|
|
||||||
* TrustZone hypervisor call
|
|
||||||
*/
|
|
||||||
void _disable_outer_l2_cache()
|
|
||||||
{
|
|
||||||
asm volatile (
|
|
||||||
"stmfd sp!, {r0-r12} \n"
|
|
||||||
"mov r0, #0 \n"
|
|
||||||
"ldr r12, =0x102 \n"
|
|
||||||
"dsb \n"
|
|
||||||
"smc #0 \n"
|
|
||||||
"ldmfd sp!, {r0-r12}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor - ensures that core never gets a pagefault
|
|
||||||
*/
|
|
||||||
Core_tlb()
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Disable L2-cache by now, or we get into deep trouble with the MMU
|
|
||||||
* not using the L2 cache
|
|
||||||
*/
|
|
||||||
_disable_outer_l2_cache();
|
|
||||||
|
|
||||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
|
||||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
|
||||||
map_core_area(Board::MMIO_1_BASE, Board::MMIO_1_SIZE, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _PANDA__TLB_H_ */
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Translation lookaside buffer
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2012-04-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _PBXA9__TLB_H_
|
|
||||||
#define _PBXA9__TLB_H_
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <board.h>
|
|
||||||
#include <tlb/arm_v7.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
class Tlb : public Arm_v7::Section_table { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation lookaside buffer of core
|
|
||||||
*/
|
|
||||||
class Core_tlb : public Tlb
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor - ensures that core never gets a pagefault
|
|
||||||
*/
|
|
||||||
Core_tlb()
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
|
||||||
map_core_area(Board::RAM_1_BASE, Board::RAM_1_SIZE, 0);
|
|
||||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
|
||||||
map_core_area(Board::MMIO_1_BASE, Board::MMIO_1_SIZE, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _PBXA9__TLB_H_ */
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Platform implementation specific for hw
|
* \brief Platform implementation specific for hw
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2011-12-21
|
* \date 2011-12-21
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -18,9 +19,14 @@
|
|||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <core_parent.h>
|
#include <core_parent.h>
|
||||||
|
#include <page_slab.h>
|
||||||
|
#include <map_local.h>
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <pic.h>
|
#include <platform_pd.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
#include <pic.h>
|
||||||
|
#include <kernel/kernel.h>
|
||||||
|
#include <translation_table.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
@ -86,12 +92,6 @@ Native_region * Platform::_core_only_ram_regions(unsigned const i)
|
|||||||
{
|
{
|
||||||
static Native_region _r[] =
|
static Native_region _r[] =
|
||||||
{
|
{
|
||||||
/* avoid null pointers */
|
|
||||||
{ 0, 1 },
|
|
||||||
|
|
||||||
/* mode transition region */
|
|
||||||
{ Kernel::mode_transition_base(), Kernel::mode_transition_size() },
|
|
||||||
|
|
||||||
/* core image */
|
/* core image */
|
||||||
{ (addr_t)&_prog_img_beg,
|
{ (addr_t)&_prog_img_beg,
|
||||||
(size_t)((addr_t)&_prog_img_end - (addr_t)&_prog_img_beg) },
|
(size_t)((addr_t)&_prog_img_end - (addr_t)&_prog_img_beg) },
|
||||||
@ -103,22 +103,32 @@ Native_region * Platform::_core_only_ram_regions(unsigned const i)
|
|||||||
return i < sizeof(_r)/sizeof(_r[0]) ? &_r[i] : 0;
|
return i < sizeof(_r)/sizeof(_r[0]) ? &_r[i] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
Platform::Platform()
|
||||||
:
|
:
|
||||||
_core_mem_alloc(0),
|
_io_mem_alloc(core_mem_alloc()),
|
||||||
_io_mem_alloc(core_mem_alloc()), _io_port_alloc(core_mem_alloc()),
|
|
||||||
_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()->page_slab(&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
|
||||||
* used by the other allocators.
|
* used by the other allocators.
|
||||||
*/
|
*/
|
||||||
enum { VERBOSE = 0 };
|
enum { VERBOSE = 0 };
|
||||||
unsigned const psl2 = get_page_size_log2();
|
init_alloc(_core_mem_alloc.phys_alloc(), _ram_regions,
|
||||||
init_alloc(&_core_mem_alloc, _ram_regions, _core_only_ram_regions, psl2);
|
_core_only_ram_regions, get_page_size_log2());
|
||||||
|
init_alloc(_core_mem_alloc.virt_alloc(), virt_region,
|
||||||
|
_core_only_ram_regions, get_page_size_log2());
|
||||||
|
|
||||||
/* make interrupts available to the interrupt allocator */
|
/* make interrupts available to the interrupt allocator */
|
||||||
for (unsigned i = 0; i < Kernel::Pic::MAX_INTERRUPT_ID; i++)
|
for (unsigned i = 0; i < Kernel::Pic::MAX_INTERRUPT_ID; i++)
|
||||||
@ -139,11 +149,16 @@ Platform::Platform()
|
|||||||
Rom_module(header->base, header->size, (const char*)header->name);
|
Rom_module(header->base, header->size, (const char*)header->name);
|
||||||
_rom_fs.insert(rom_module);
|
_rom_fs.insert(rom_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* print ressource summary */
|
/* print ressource summary */
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
printf("Core memory allocator\n");
|
printf("Core virtual memory allocator\n");
|
||||||
printf("---------------------\n");
|
printf("---------------------\n");
|
||||||
_core_mem_alloc.raw()->dump_addr_tree();
|
_core_mem_alloc.virt_alloc()->raw()->dump_addr_tree();
|
||||||
|
printf("\n");
|
||||||
|
printf("RAM memory allocator\n");
|
||||||
|
printf("---------------------\n");
|
||||||
|
_core_mem_alloc.phys_alloc()->raw()->dump_addr_tree();
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("IO memory allocator\n");
|
printf("IO memory allocator\n");
|
||||||
printf("-------------------\n");
|
printf("-------------------\n");
|
||||||
@ -171,3 +186,76 @@ void Core_parent::exit(int exit_value)
|
|||||||
while (1) ;
|
while (1) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************
|
||||||
|
** Support for core memory management **
|
||||||
|
****************************************/
|
||||||
|
|
||||||
|
bool Genode::map_local(addr_t from_phys, addr_t to_virt, size_t num_pages, bool io_mem)
|
||||||
|
{
|
||||||
|
Translation_table *tt = Kernel::core_pd()->translation_table();
|
||||||
|
const Page_flags flags = Page_flags::map_core_area(io_mem);
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (unsigned i = 0; i < 2; i++) {
|
||||||
|
try {
|
||||||
|
Lock::Guard guard(*Kernel::core_pd()->platform_pd()->lock());
|
||||||
|
|
||||||
|
tt->insert_translation(to_virt, from_phys,
|
||||||
|
num_pages * get_page_size(), flags,
|
||||||
|
Kernel::core_pd()->platform_pd()->page_slab());
|
||||||
|
return true;
|
||||||
|
} catch(Page_slab::Out_of_slabs) {
|
||||||
|
Kernel::core_pd()->platform_pd()->page_slab()->alloc_slab_block();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(Allocator::Out_of_memory) {
|
||||||
|
PERR("Translation table needs to much RAM");
|
||||||
|
} catch(...) {
|
||||||
|
PERR("Invalid mapping %p -> %p (%zx)", (void*)from_phys, (void*)to_virt,
|
||||||
|
get_page_size() * num_pages);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Genode::unmap_local(addr_t virt_addr, size_t num_pages)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Lock::Guard guard(*Kernel::core_pd()->platform_pd()->lock());
|
||||||
|
|
||||||
|
Translation_table *tt = Kernel::core_pd()->translation_table();
|
||||||
|
tt->remove_translation(virt_addr, num_pages * get_page_size(),
|
||||||
|
Kernel::core_pd()->platform_pd()->page_slab());
|
||||||
|
|
||||||
|
/* update translation caches of all processors */
|
||||||
|
Kernel::update_pd(Kernel::core_pd()->id());
|
||||||
|
return true;
|
||||||
|
} catch(...) {
|
||||||
|
PERR("tried to remove invalid region!");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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()->page_slab();
|
||||||
|
slab->backing_store(_core_mem_allocator->raw());
|
||||||
|
bool ret = ::map_local(phys_addr, virt_addr, size / get_page_size(), false);
|
||||||
|
slab->backing_store(_core_mem_allocator);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Core_mem_allocator::Mapped_mem_allocator::_unmap_local(addr_t virt_addr,
|
||||||
|
unsigned size)
|
||||||
|
{
|
||||||
|
Genode::Page_slab * slab = Kernel::core_pd()->platform_pd()->page_slab();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Protection-domain facility
|
* \brief Protection-domain facility
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-02-12
|
* \date 2012-02-12
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -18,10 +19,15 @@ using namespace Genode;
|
|||||||
|
|
||||||
Platform_pd::~Platform_pd()
|
Platform_pd::~Platform_pd()
|
||||||
{
|
{
|
||||||
_tlb->remove_region(platform()->vm_start(), platform()->vm_size());
|
Lock::Guard guard(_lock);
|
||||||
regain_ram_from_tlb(_tlb);
|
|
||||||
if (Kernel::bin_pd(_id)) {
|
if (Kernel::bin_pd(_id)) {
|
||||||
PERR("failed to destruct protection domain at kernel");
|
PERR("failed to destruct protection domain at kernel");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_tt->remove_translation(platform()->vm_start(), platform()->vm_size(),
|
||||||
|
_pslab);
|
||||||
|
|
||||||
|
/* TODO: destroy page slab and translation table!!! */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
#include <core_env.h>
|
#include <core_env.h>
|
||||||
#include <rm_session_component.h>
|
#include <rm_session_component.h>
|
||||||
|
#include <map_local.h>
|
||||||
|
|
||||||
|
#include <kernel/pd.h>
|
||||||
|
|
||||||
/* kernel includes */
|
/* kernel includes */
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
@ -51,19 +54,16 @@ Platform_thread::~Platform_thread()
|
|||||||
/* the RM client may be destructed before platform thread */
|
/* the RM client may be destructed before platform thread */
|
||||||
if (_rm_client) {
|
if (_rm_client) {
|
||||||
Rm_session_component * const rm = _rm_client->member_rm_session();
|
Rm_session_component * const rm = _rm_client->member_rm_session();
|
||||||
rm->detach(_utcb_virt);
|
rm->detach(_utcb_pd_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free UTCB */
|
/* free UTCB */
|
||||||
if (_pd == Kernel::core_pd()->platform_pd()) {
|
Ram_session_component * const ram =
|
||||||
Range_allocator * const ram = platform()->ram_alloc();
|
dynamic_cast<Ram_session_component *>(core_env()->ram_session());
|
||||||
ram->free(_utcb_phys, sizeof(Native_utcb));
|
assert(ram);
|
||||||
} else {
|
ram->free(_utcb);
|
||||||
Ram_session_component * const ram =
|
|
||||||
dynamic_cast<Ram_session_component *>(core_env()->ram_session());
|
|
||||||
assert(ram);
|
|
||||||
ram->free(_utcb);
|
|
||||||
}
|
|
||||||
/* release from pager */
|
/* release from pager */
|
||||||
if (_rm_client) {
|
if (_rm_client) {
|
||||||
Pager_object * const object = dynamic_cast<Pager_object *>(_rm_client);
|
Pager_object * const object = dynamic_cast<Pager_object *>(_rm_client);
|
||||||
@ -78,29 +78,27 @@ Platform_thread::~Platform_thread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Platform_thread::Platform_thread(size_t const stack_size,
|
Platform_thread::Platform_thread(const char * const label,
|
||||||
const char * const label)
|
Native_utcb * utcb)
|
||||||
:
|
: _pd(Kernel::core_pd()->platform_pd()),
|
||||||
_stack_size(stack_size),
|
_rm_client(0),
|
||||||
_pd(Kernel::core_pd()->platform_pd()),
|
_utcb_core_addr(utcb),
|
||||||
_rm_client(0),
|
_utcb_pd_addr(utcb),
|
||||||
_utcb_virt(0),
|
_main_thread(0)
|
||||||
_main_thread(0)
|
|
||||||
{
|
{
|
||||||
strncpy(_label, label, LABEL_MAX_LEN);
|
strncpy(_label, label, LABEL_MAX_LEN);
|
||||||
|
|
||||||
/* create UTCB for a core thread */
|
/* create UTCB for a core thread */
|
||||||
Range_allocator * const ram = platform()->ram_alloc();
|
void *utcb_phys;
|
||||||
if (!ram->alloc_aligned(sizeof(Native_utcb), (void **)&_utcb_phys,
|
if (!platform()->ram_alloc()->alloc(sizeof(Native_utcb), &utcb_phys)) {
|
||||||
MIN_MAPPING_SIZE_LOG2).is_ok())
|
|
||||||
{
|
|
||||||
PERR("failed to allocate UTCB");
|
PERR("failed to allocate UTCB");
|
||||||
throw Cpu_session::Out_of_metadata();
|
throw Cpu_session::Out_of_metadata();
|
||||||
}
|
}
|
||||||
_utcb_virt = _utcb_phys;
|
map_local((addr_t)utcb_phys, (addr_t)_utcb_core_addr,
|
||||||
|
sizeof(Native_utcb) / get_page_size());
|
||||||
|
|
||||||
/* set-up default start-info */
|
/* set-up default start-info */
|
||||||
_utcb_virt->core_start_info()->init(Processor_driver::primary_id());
|
_utcb_core_addr->core_start_info()->init(Processor_driver::primary_id());
|
||||||
|
|
||||||
/* create kernel object */
|
/* create kernel object */
|
||||||
_id = Kernel::new_thread(_kernel_thread, Kernel::Priority::MAX, _label);
|
_id = Kernel::new_thread(_kernel_thread, Kernel::Priority::MAX, _label);
|
||||||
@ -115,10 +113,9 @@ Platform_thread::Platform_thread(const char * const label,
|
|||||||
unsigned const virt_prio,
|
unsigned const virt_prio,
|
||||||
addr_t const utcb)
|
addr_t const utcb)
|
||||||
:
|
:
|
||||||
_stack_size(0),
|
|
||||||
_pd(nullptr),
|
_pd(nullptr),
|
||||||
_rm_client(0),
|
_rm_client(0),
|
||||||
_utcb_virt((Native_utcb *)utcb),
|
_utcb_pd_addr((Native_utcb *)utcb),
|
||||||
_main_thread(0)
|
_main_thread(0)
|
||||||
{
|
{
|
||||||
strncpy(_label, label, LABEL_MAX_LEN);
|
strncpy(_label, label, LABEL_MAX_LEN);
|
||||||
@ -136,7 +133,7 @@ Platform_thread::Platform_thread(const char * const label,
|
|||||||
PERR("failed to allocate UTCB");
|
PERR("failed to allocate UTCB");
|
||||||
throw Cpu_session::Out_of_metadata();
|
throw Cpu_session::Out_of_metadata();
|
||||||
}
|
}
|
||||||
_utcb_phys = (Native_utcb *)ram->phys_addr(_utcb);
|
_utcb_core_addr = (Native_utcb *)core_env()->rm_session()->attach(_utcb);
|
||||||
|
|
||||||
/* create kernel object */
|
/* create kernel object */
|
||||||
enum { MAX_PRIO = Kernel::Priority::MAX };
|
enum { MAX_PRIO = Kernel::Priority::MAX };
|
||||||
@ -157,6 +154,7 @@ int Platform_thread::join_pd(Platform_pd * pd, bool const main_thread,
|
|||||||
PERR("thread already in another protection domain");
|
PERR("thread already in another protection domain");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* join protection domain */
|
/* join protection domain */
|
||||||
_pd = pd;
|
_pd = pd;
|
||||||
_main_thread = main_thread;
|
_main_thread = main_thread;
|
||||||
@ -178,13 +176,13 @@ int Platform_thread::start(void * const ip, void * const sp)
|
|||||||
{
|
{
|
||||||
/* attach UTCB in case of a main thread */
|
/* attach UTCB in case of a main thread */
|
||||||
if (_main_thread) {
|
if (_main_thread) {
|
||||||
_utcb_virt = main_thread_utcb();
|
_utcb_pd_addr = UTCB_MAIN_THREAD;
|
||||||
if (!_rm_client) {
|
if (!_rm_client) {
|
||||||
PERR("invalid RM client");
|
PERR("invalid RM client");
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
Rm_session_component * const rm = _rm_client->member_rm_session();
|
Rm_session_component * const rm = _rm_client->member_rm_session();
|
||||||
try { rm->attach(_utcb, 0, 0, true, _utcb_virt, 0); }
|
try { rm->attach(_utcb, 0, 0, true, _utcb_pd_addr, 0); }
|
||||||
catch (...) {
|
catch (...) {
|
||||||
PERR("failed to attach UTCB");
|
PERR("failed to attach UTCB");
|
||||||
return -1;
|
return -1;
|
||||||
@ -207,9 +205,8 @@ int Platform_thread::start(void * const ip, void * const sp)
|
|||||||
else { processor_id = Processor_driver::primary_id(); }
|
else { processor_id = Processor_driver::primary_id(); }
|
||||||
|
|
||||||
/* start executing new thread */
|
/* start executing new thread */
|
||||||
_utcb_phys->start_info()->init(_id, _utcb);
|
_utcb_core_addr->start_info()->init(_id, _utcb);
|
||||||
_tlb = Kernel::start_thread(_id, processor_id, _pd->id(), _utcb_phys);
|
if (!Kernel::start_thread(_id, processor_id, _pd->id(), _utcb_core_addr)) {
|
||||||
if (!_tlb) {
|
|
||||||
PERR("failed to start thread");
|
PERR("failed to start thread");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* \brief CPU driver for core
|
* \brief CPU driver for core
|
||||||
* \author Martin stein
|
* \author Martin stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-09-11
|
* \date 2012-09-11
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -514,18 +515,18 @@ namespace Arm
|
|||||||
** files. So take care if you attempt to change them. **
|
** files. So take care if you attempt to change them. **
|
||||||
**********************************************************/
|
**********************************************************/
|
||||||
|
|
||||||
uint32_t cidr; /* context ID register backup */
|
uint32_t cidr; /* context ID register backup */
|
||||||
uint32_t section_table; /* base address of applied section table */
|
uint32_t t_table; /* base address of applied translation table */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get base of assigned translation lookaside buffer
|
* Get base of assigned translation lookaside buffer
|
||||||
*/
|
*/
|
||||||
addr_t tlb() const { return section_table; }
|
addr_t translation_table() const { return t_table; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign translation lookaside buffer
|
* Assign translation lookaside buffer
|
||||||
*/
|
*/
|
||||||
void tlb(addr_t const st) { section_table = st; }
|
void translation_table(addr_t const tt) { t_table = tt; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign protection domain
|
* Assign protection domain
|
||||||
@ -567,13 +568,13 @@ namespace Arm
|
|||||||
/**
|
/**
|
||||||
* Initialize thread context
|
* Initialize thread context
|
||||||
*
|
*
|
||||||
* \param tlb physical base of appropriate page table
|
* \param tt physical base of appropriate translation table
|
||||||
* \param pd_id kernel name of appropriate protection domain
|
* \param pd_id kernel name of appropriate protection domain
|
||||||
*/
|
*/
|
||||||
void init_thread(addr_t const tlb, unsigned const pd_id)
|
void init_thread(addr_t const tt, unsigned const pd_id)
|
||||||
{
|
{
|
||||||
cidr = pd_id;
|
cidr = pd_id;
|
||||||
section_table = tlb;
|
t_table = tt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Export RAM dataspace as shared memory object (dummy)
|
* \brief Export RAM dataspace as shared memory object (dummy)
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-02-12
|
* \date 2012-02-12
|
||||||
|
*
|
||||||
|
* TODO: this file is almost identical to
|
||||||
|
* base-okl4/src/core/ram_session_support.cc, we should merge them
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -14,26 +18,47 @@
|
|||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
|
|
||||||
/* base-hw includes */
|
|
||||||
#include <kernel/core_interface.h>
|
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <ram_session_component.h>
|
#include <ram_session_component.h>
|
||||||
|
#include <platform.h>
|
||||||
|
#include <map_local.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
void Ram_session_component::_export_ram_ds(Dataspace_component *ds) { }
|
void Ram_session_component::_export_ram_ds(Dataspace_component *ds) { }
|
||||||
|
|
||||||
|
|
||||||
void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds) { }
|
void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds) { }
|
||||||
|
|
||||||
|
|
||||||
void Ram_session_component::_clear_ds (Dataspace_component * ds)
|
void Ram_session_component::_clear_ds (Dataspace_component * ds)
|
||||||
{
|
{
|
||||||
memset((void *)ds->phys_addr(), 0, ds->size());
|
size_t page_rounded_size = (ds->size() + get_page_size() - 1) & get_page_mask();
|
||||||
|
|
||||||
/* make the new DS-content visible to other PDs */
|
/* allocate range in core's virtual address space */
|
||||||
Kernel::update_data_region(ds->phys_addr(), ds->size());
|
void *virt_addr;
|
||||||
|
if (!platform()->region_alloc()->alloc(page_rounded_size, &virt_addr)) {
|
||||||
|
PERR("could not allocate virtual address range in core of size %zd\n",
|
||||||
|
page_rounded_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* map the dataspace's physical pages to corresponding virtual addresses */
|
||||||
|
size_t num_pages = page_rounded_size >> get_page_size_log2();
|
||||||
|
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages)) {
|
||||||
|
PERR("core-local memory mapping failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear dataspace */
|
||||||
|
memset(virt_addr, 0, page_rounded_size);
|
||||||
|
|
||||||
|
/* uncached dataspaces need to be flushed */
|
||||||
|
if (ds->write_combined())
|
||||||
|
Kernel::update_data_region((addr_t)virt_addr, page_rounded_size);
|
||||||
|
|
||||||
|
/* unmap dataspace from core */
|
||||||
|
if (!unmap_local((addr_t)virt_addr, num_pages))
|
||||||
|
PERR("could not unmap core-local address range at %p", virt_addr);
|
||||||
|
|
||||||
|
/* free core's virtual address space */
|
||||||
|
platform()->region_alloc()->free(virt_addr, page_rounded_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,24 +20,11 @@
|
|||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <platform_pd.h>
|
#include <platform_pd.h>
|
||||||
#include <platform_thread.h>
|
#include <platform_thread.h>
|
||||||
#include <tlb.h>
|
#include <translation_table.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
/**************************************
|
|
||||||
** Helpers for processor broadcasts **
|
|
||||||
**************************************/
|
|
||||||
|
|
||||||
struct Update_pd_data { unsigned const pd_id; };
|
|
||||||
|
|
||||||
void update_pd(void * const data)
|
|
||||||
{
|
|
||||||
auto const d = reinterpret_cast<Update_pd_data *>(data);
|
|
||||||
Kernel::update_pd(d->pd_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
** Rm_client **
|
** Rm_client **
|
||||||
***************/
|
***************/
|
||||||
@ -46,22 +33,19 @@ void Rm_client::unmap(addr_t, addr_t virt_base, size_t size)
|
|||||||
{
|
{
|
||||||
/* remove mapping from the translation table of the thread that we serve */
|
/* remove mapping from the translation table of the thread that we serve */
|
||||||
Platform_thread * const pt = (Platform_thread *)badge();
|
Platform_thread * const pt = (Platform_thread *)badge();
|
||||||
if (!pt) {
|
if (!pt || !pt->pd()) return;
|
||||||
PWRN("failed to get platform thread of RM client");
|
|
||||||
|
Lock::Guard guard(*pt->pd()->lock());
|
||||||
|
|
||||||
|
Translation_table * const tt = pt->pd()->translation_table();
|
||||||
|
if (!tt) {
|
||||||
|
PWRN("failed to get translation table of RM client");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Tlb * const tlb = pt->tlb();
|
tt->remove_translation(virt_base, size,pt->pd()->page_slab());
|
||||||
if (!tlb) {
|
|
||||||
PWRN("failed to get page table of RM client");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tlb->remove_region(virt_base, size);
|
|
||||||
|
|
||||||
/* update translation caches of all processors */
|
/* update translation caches of all processors */
|
||||||
Kernel::update_pd(pt->pd()->id());
|
Kernel::update_pd(pt->pd()->id());
|
||||||
|
|
||||||
/* try to get back released memory from the translation table */
|
|
||||||
regain_ram_from_tlb(tlb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -72,37 +56,36 @@ void Rm_client::unmap(addr_t, addr_t virt_base, size_t size)
|
|||||||
int Pager_activation_base::apply_mapping()
|
int Pager_activation_base::apply_mapping()
|
||||||
{
|
{
|
||||||
/* prepare mapping */
|
/* prepare mapping */
|
||||||
Tlb * const tlb = (Tlb *)_fault.tlb;
|
Platform_pd * const pd = (Platform_pd*)_fault.pd;
|
||||||
|
|
||||||
|
Lock::Guard guard(*pd->lock());
|
||||||
|
|
||||||
|
Translation_table * const tt = pd->translation_table();
|
||||||
|
Page_slab * page_slab = pd->page_slab();
|
||||||
|
|
||||||
Page_flags const flags =
|
Page_flags const flags =
|
||||||
Page_flags::apply_mapping(_mapping.writable,
|
Page_flags::apply_mapping(_mapping.writable,
|
||||||
_mapping.write_combined,
|
_mapping.write_combined,
|
||||||
_mapping.io_mem);
|
_mapping.io_mem);
|
||||||
|
|
||||||
/* insert mapping into TLB */
|
/* insert mapping into translation table */
|
||||||
unsigned sl2;
|
try {
|
||||||
sl2 = tlb->insert_translation(_mapping.virt_address, _mapping.phys_address,
|
for (unsigned retry = 0; retry < 2; retry++) {
|
||||||
_mapping.size_log2, flags);
|
try {
|
||||||
if (sl2)
|
tt->insert_translation(_mapping.virt_address, _mapping.phys_address,
|
||||||
{
|
1 << _mapping.size_log2, flags, page_slab);
|
||||||
/* try to get some natural aligned RAM */
|
return 0;
|
||||||
void * ram;
|
} catch(Page_slab::Out_of_slabs) {
|
||||||
bool ram_ok = platform()->ram_alloc()->alloc_aligned(1<<sl2, &ram,
|
page_slab->alloc_slab_block();
|
||||||
sl2).is_ok();
|
}
|
||||||
if (!ram_ok) {
|
|
||||||
PWRN("failed to allocate additional RAM for TLB");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* try to translate again with extra RAM */
|
|
||||||
sl2 = tlb->insert_translation(_mapping.virt_address,
|
|
||||||
_mapping.phys_address,
|
|
||||||
_mapping.size_log2, flags, ram);
|
|
||||||
if (sl2) {
|
|
||||||
PWRN("TLB needs to much RAM");
|
|
||||||
regain_ram_from_tlb(tlb);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
} catch(Allocator::Out_of_memory) {
|
||||||
|
PERR("Translation table needs to much RAM");
|
||||||
|
} catch(...) {
|
||||||
|
PERR("Invalid mapping %p -> %p (%zx)", (void*)_mapping.phys_address,
|
||||||
|
(void*)_mapping.virt_address, 1 << _mapping.size_log2);
|
||||||
}
|
}
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Translation lookaside buffer
|
|
||||||
* \author Norman Feske
|
|
||||||
* \author Martin stein
|
|
||||||
* \date 2012-08-30
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _RPI__TLB_H_
|
|
||||||
#define _RPI__TLB_H_
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <tlb/arm_v6.h>
|
|
||||||
#include <board.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
class Tlb : public Arm_v6::Section_table { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation lookaside buffer of core
|
|
||||||
*/
|
|
||||||
class Core_tlb : public Tlb
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor - ensures that core never gets a pagefault
|
|
||||||
*/
|
|
||||||
Core_tlb()
|
|
||||||
{
|
|
||||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
|
||||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _RPI__TLB_H_ */
|
|
||||||
|
|
@ -29,6 +29,8 @@ INC_DIR += $(REP_DIR)/src/core \
|
|||||||
SRC_CC += console.cc \
|
SRC_CC += console.cc \
|
||||||
cpu_session_component.cc \
|
cpu_session_component.cc \
|
||||||
cpu_session_support.cc \
|
cpu_session_support.cc \
|
||||||
|
core_rm_session.cc \
|
||||||
|
core_mem_alloc.cc \
|
||||||
dataspace_component.cc \
|
dataspace_component.cc \
|
||||||
dump_alloc.cc \
|
dump_alloc.cc \
|
||||||
io_mem_session_component.cc \
|
io_mem_session_component.cc \
|
||||||
@ -47,6 +49,7 @@ SRC_CC += console.cc \
|
|||||||
signal_session_component.cc \
|
signal_session_component.cc \
|
||||||
trace_session_component.cc \
|
trace_session_component.cc \
|
||||||
thread.cc \
|
thread.cc \
|
||||||
|
thread_support.cc \
|
||||||
kernel/kernel.cc \
|
kernel/kernel.cc \
|
||||||
kernel/thread.cc \
|
kernel/thread.cc \
|
||||||
kernel/vm.cc \
|
kernel/vm.cc \
|
||||||
@ -75,8 +78,11 @@ vpath rm_session_component.cc $(BASE_DIR)/src/core
|
|||||||
vpath rom_session_component.cc $(BASE_DIR)/src/core
|
vpath rom_session_component.cc $(BASE_DIR)/src/core
|
||||||
vpath trace_session_component.cc $(BASE_DIR)/src/core
|
vpath trace_session_component.cc $(BASE_DIR)/src/core
|
||||||
vpath dump_alloc.cc $(BASE_DIR)/src/core
|
vpath dump_alloc.cc $(BASE_DIR)/src/core
|
||||||
|
vpath context_area.cc $(BASE_DIR)/src/core
|
||||||
|
vpath core_mem_alloc.cc $(BASE_DIR)/src/core
|
||||||
vpath console.cc $(REP_DIR)/src/base
|
vpath console.cc $(REP_DIR)/src/base
|
||||||
vpath pager.cc $(REP_DIR)/src/base
|
vpath pager.cc $(REP_DIR)/src/base
|
||||||
vpath _main.cc $(BASE_DIR)/src/platform
|
vpath _main.cc $(BASE_DIR)/src/platform
|
||||||
|
vpath thread.cc $(BASE_DIR)/src/base/thread
|
||||||
vpath % $(REP_DIR)/src/core
|
vpath % $(REP_DIR)/src/core
|
||||||
|
|
||||||
|
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Implementation of Thread API interface for core
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2012-01-25
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <base/thread.h>
|
|
||||||
#include <base/env.h>
|
|
||||||
#include <kernel/log.h>
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <platform.h>
|
|
||||||
#include <platform_thread.h>
|
|
||||||
#include <kernel/kernel.h>
|
|
||||||
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
extern Genode::Native_utcb * _main_thread_utcb;
|
|
||||||
|
|
||||||
namespace Kernel { unsigned core_id(); }
|
|
||||||
|
|
||||||
|
|
||||||
Native_utcb * Thread_base::utcb()
|
|
||||||
{
|
|
||||||
if (this) { return _tid.platform_thread->utcb_virt(); }
|
|
||||||
return _main_thread_utcb;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Thread_base * Thread_base::myself()
|
|
||||||
{
|
|
||||||
/* get thread ident from the aligned base of the stack */
|
|
||||||
int dummy = 0;
|
|
||||||
addr_t sp = (addr_t)(&dummy);
|
|
||||||
enum { SP_MASK = ~((1 << CORE_STACK_ALIGNM_LOG2) - 1) };
|
|
||||||
Core_thread_id id = *(Core_thread_id *)((addr_t)sp & SP_MASK);
|
|
||||||
return (Thread_base *)id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::_thread_start()
|
|
||||||
{
|
|
||||||
/* this is never called by the main thread */
|
|
||||||
Thread_base::myself()->_thread_bootstrap();
|
|
||||||
Thread_base::myself()->entry();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Thread_base::Thread_base(const char * const label, size_t const stack_size, Type)
|
|
||||||
{
|
|
||||||
_tid.platform_thread = new (platform()->core_mem_alloc())
|
|
||||||
Platform_thread(stack_size, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Thread_base::~Thread_base()
|
|
||||||
{
|
|
||||||
Kernel::log() << __PRETTY_FUNCTION__ << "not implemented\n";
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::start()
|
|
||||||
{
|
|
||||||
/* allocate stack memory that fullfills the constraints for core stacks */
|
|
||||||
size_t const size = _tid.platform_thread->stack_size();
|
|
||||||
if (size > (1 << CORE_STACK_ALIGNM_LOG2) - sizeof(Core_thread_id)) {
|
|
||||||
PERR("stack size does not fit stack alignment of core");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
void * base;
|
|
||||||
Platform * const p = static_cast<Platform *>(platform());
|
|
||||||
Range_allocator * const alloc = p->core_mem_alloc();
|
|
||||||
if (alloc->alloc_aligned(size, &base, CORE_STACK_ALIGNM_LOG2).is_error()) {
|
|
||||||
PERR("failed to allocate stack memory");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* provide thread ident at the aligned base of the stack */
|
|
||||||
*(Core_thread_id *)base = (Core_thread_id)this;
|
|
||||||
|
|
||||||
/* set affinity of thread */
|
|
||||||
Platform_thread * const platform_thread = _tid.platform_thread;
|
|
||||||
unsigned const processor_id = utcb()->core_start_info()->processor_id();
|
|
||||||
Affinity::Location location(processor_id, 0, 1, 1);
|
|
||||||
platform_thread->affinity(location);
|
|
||||||
|
|
||||||
/* start thread with stack pointer at the top of stack */
|
|
||||||
void * sp = (void *)((addr_t)base + size);
|
|
||||||
void * ip = (void *)&_thread_start;
|
|
||||||
if (platform_thread->start(ip, sp)) {
|
|
||||||
PERR("failed to start thread");
|
|
||||||
alloc->free(base, size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::join()
|
|
||||||
{
|
|
||||||
_join_lock.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Thread_base::cancel_blocking()
|
|
||||||
{
|
|
||||||
_tid.platform_thread->cancel_blocking();
|
|
||||||
}
|
|
||||||
|
|
62
base-hw/src/core/thread_support.cc
Normal file
62
base-hw/src/core/thread_support.cc
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* \brief Implementation of Thread API interface for core
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2014-02-27
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <base/thread.h>
|
||||||
|
#include <base/sleep.h>
|
||||||
|
#include <base/env.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <platform.h>
|
||||||
|
#include <platform_thread.h>
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
extern Genode::Native_utcb * _main_thread_utcb;
|
||||||
|
|
||||||
|
Native_utcb * main_thread_utcb() {
|
||||||
|
return _main_thread_utcb; }
|
||||||
|
|
||||||
|
|
||||||
|
void Thread_base::start()
|
||||||
|
{
|
||||||
|
/* start thread with stack pointer at the top of stack */
|
||||||
|
if (_tid.platform_thread->start((void *)&_thread_start, stack_top()))
|
||||||
|
PERR("failed to start thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Thread_base::cancel_blocking()
|
||||||
|
{
|
||||||
|
_tid.platform_thread->cancel_blocking();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Thread_base::_deinit_platform_thread()
|
||||||
|
{
|
||||||
|
/* destruct platform thread */
|
||||||
|
destroy(platform()->core_mem_alloc(), _tid.platform_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Thread_base::_init_platform_thread(Type type)
|
||||||
|
{
|
||||||
|
/* create platform thread */
|
||||||
|
_tid.platform_thread = new (platform()->core_mem_alloc())
|
||||||
|
Platform_thread(_context->name, &_context->utcb);
|
||||||
|
|
||||||
|
if (type == NORMAL) { return; }
|
||||||
|
|
||||||
|
PWRN("not implemented!");
|
||||||
|
}
|
@ -1,825 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief TLB driver for core
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2012-02-22
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _TLB__ARM_H_
|
|
||||||
#define _TLB__ARM_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <util/register.h>
|
|
||||||
#include <base/printf.h>
|
|
||||||
|
|
||||||
/* base-hw includes */
|
|
||||||
#include <placement_new.h>
|
|
||||||
#include <tlb/page_flags.h>
|
|
||||||
|
|
||||||
namespace Arm
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if 'p' is aligned to 1 << 'alignm_log2'
|
|
||||||
*/
|
|
||||||
inline bool aligned(addr_t const a, size_t const alignm_log2) {
|
|
||||||
return a == ((a >> alignm_log2) << alignm_log2); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return permission configuration according to given mapping flags
|
|
||||||
*
|
|
||||||
* \param T targeted translation-table-descriptor type
|
|
||||||
* \param flags mapping flags
|
|
||||||
*
|
|
||||||
* \return descriptor value with AP and XN set and the rest left zero
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
static typename T::access_t
|
|
||||||
access_permission_bits(Page_flags const & flags)
|
|
||||||
{
|
|
||||||
typedef typename T::Xn Xn;
|
|
||||||
typedef typename T::Ap Ap;
|
|
||||||
typedef typename T::access_t access_t;
|
|
||||||
bool const w = flags.writeable;
|
|
||||||
bool const p = flags.privileged;
|
|
||||||
access_t ap;
|
|
||||||
if (w) { if (p) { ap = Ap::bits(0b001); }
|
|
||||||
else { ap = Ap::bits(0b011); }
|
|
||||||
} else { if (p) { ap = Ap::bits(0b101); }
|
|
||||||
else { ap = Ap::bits(0b010); }
|
|
||||||
}
|
|
||||||
return Xn::bits(!flags.executable) | ap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Memory region attributes for the translation descriptor 'T'
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
static typename T::access_t
|
|
||||||
memory_region_attr(Page_flags const & flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Second level translation table
|
|
||||||
*/
|
|
||||||
class Page_table
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
_1KB_LOG2 = 10,
|
|
||||||
_4KB_LOG2 = 12,
|
|
||||||
_64KB_LOG2 = 16,
|
|
||||||
_1MB_LOG2 = 20,
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum {
|
|
||||||
SIZE_LOG2 = _1KB_LOG2,
|
|
||||||
SIZE = 1 << SIZE_LOG2,
|
|
||||||
ALIGNM_LOG2 = SIZE_LOG2,
|
|
||||||
|
|
||||||
VIRT_SIZE_LOG2 = _1MB_LOG2,
|
|
||||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
|
||||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common descriptor structure
|
|
||||||
*/
|
|
||||||
struct Descriptor : Register<32>
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Descriptor types
|
|
||||||
*/
|
|
||||||
enum Type { FAULT, SMALL_PAGE };
|
|
||||||
|
|
||||||
struct Type_0 : Bitfield<0, 2> { };
|
|
||||||
struct Type_1 : Bitfield<1, 1> { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get descriptor type of 'v'
|
|
||||||
*/
|
|
||||||
static Type type(access_t const v)
|
|
||||||
{
|
|
||||||
access_t const t0 = Type_0::get(v);
|
|
||||||
if (t0 == 0) { return FAULT; }
|
|
||||||
access_t const t1 = Type_1::get(v);
|
|
||||||
if (t1 == 1) return SMALL_PAGE;
|
|
||||||
return FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set descriptor type of 'v'
|
|
||||||
*/
|
|
||||||
static void type(access_t & v, Type const t)
|
|
||||||
{
|
|
||||||
switch (t) {
|
|
||||||
case FAULT:
|
|
||||||
Type_0::set(v, 0);
|
|
||||||
return;
|
|
||||||
case SMALL_PAGE:
|
|
||||||
Type_1::set(v, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invalidate descriptor 'v'
|
|
||||||
*/
|
|
||||||
static void invalidate(access_t & v) { type(v, FAULT); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return if descriptor 'v' is valid
|
|
||||||
*/
|
|
||||||
static bool valid(access_t & v) { return type(v) != FAULT; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an untranslated virtual region
|
|
||||||
*/
|
|
||||||
struct Fault : Descriptor
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
VIRT_SIZE_LOG2 = _4KB_LOG2,
|
|
||||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
|
||||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Small page descriptor structure
|
|
||||||
*/
|
|
||||||
struct Small_page : Descriptor
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
VIRT_SIZE_LOG2 = _4KB_LOG2,
|
|
||||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
|
||||||
VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1,
|
|
||||||
VIRT_BASE_MASK = ~(VIRT_OFFSET_MASK),
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Xn : Bitfield<0, 1> { }; /* execute never */
|
|
||||||
struct B : Bitfield<2, 1> { }; /* mem region attr. */
|
|
||||||
struct C : Bitfield<3, 1> { }; /* mem region attr. */
|
|
||||||
struct Ap_0 : Bitfield<4, 2> { }; /* access permission */
|
|
||||||
struct Tex : Bitfield<6, 3> { }; /* mem region attr. */
|
|
||||||
struct Ap_1 : Bitfield<9, 1> { }; /* access permission */
|
|
||||||
struct S : Bitfield<10, 1> { }; /* shareable bit */
|
|
||||||
struct Ng : Bitfield<11, 1> { }; /* not global bit */
|
|
||||||
struct Pa_31_12 : Bitfield<12, 20> { }; /* physical base */
|
|
||||||
|
|
||||||
struct Ap : Bitset_2<Ap_0, Ap_1> { }; /* access permission */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compose descriptor value
|
|
||||||
*/
|
|
||||||
static access_t create(Page_flags const & flags,
|
|
||||||
addr_t const pa)
|
|
||||||
{
|
|
||||||
access_t v = access_permission_bits<Small_page>(flags);
|
|
||||||
v |= memory_region_attr<Small_page>(flags);
|
|
||||||
v |= Ng::bits(!flags.global);
|
|
||||||
v |= S::bits(1);
|
|
||||||
v |= Pa_31_12::masked(pa);
|
|
||||||
Descriptor::type(v, Descriptor::SMALL_PAGE);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Table payload
|
|
||||||
*
|
|
||||||
* Must be the only member of this class
|
|
||||||
*/
|
|
||||||
Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)];
|
|
||||||
|
|
||||||
enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get entry index by virtual offset
|
|
||||||
*
|
|
||||||
* \param i is overridden with the index if call returns 0
|
|
||||||
* \param vo virtual offset relative to the virtual table base
|
|
||||||
*
|
|
||||||
* \retval 0 on success
|
|
||||||
* \retval <0 translation failed
|
|
||||||
*/
|
|
||||||
int _index_by_vo (unsigned & i, addr_t const vo) const
|
|
||||||
{
|
|
||||||
if (vo > max_virt_offset()) return -1;
|
|
||||||
i = vo >> Small_page::VIRT_SIZE_LOG2;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Page_table()
|
|
||||||
{
|
|
||||||
/* check table alignment */
|
|
||||||
if (!aligned((addr_t)this, ALIGNM_LOG2) ||
|
|
||||||
(addr_t)this != (addr_t)_entries)
|
|
||||||
{
|
|
||||||
PDBG("Insufficient table alignment");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
/* start with an empty table */
|
|
||||||
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
|
||||||
Descriptor::invalidate(_entries[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum virtual offset that can be translated by this table
|
|
||||||
*/
|
|
||||||
static addr_t max_virt_offset()
|
|
||||||
{
|
|
||||||
return (MAX_INDEX << Small_page::VIRT_SIZE_LOG2)
|
|
||||||
+ (Small_page::VIRT_SIZE - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert one atomic translation 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_log2 log2(Size of the translated region),
|
|
||||||
* must be supported by this table
|
|
||||||
* \param flags mapping flags
|
|
||||||
*
|
|
||||||
* This method overrides an existing translation in case
|
|
||||||
* that it spans the the same virtual range and is not
|
|
||||||
* a link to another table level.
|
|
||||||
*/
|
|
||||||
void insert_translation(addr_t const vo, addr_t const pa,
|
|
||||||
size_t const size_log2,
|
|
||||||
Page_flags const & flags)
|
|
||||||
{
|
|
||||||
/* validate virtual address */
|
|
||||||
unsigned i;
|
|
||||||
if (_index_by_vo (i, vo)) {
|
|
||||||
PDBG("Invalid virtual offset");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
/* select descriptor type by the translation size */
|
|
||||||
if (size_log2 == Small_page::VIRT_SIZE_LOG2)
|
|
||||||
{
|
|
||||||
/* compose new descriptor value */
|
|
||||||
Descriptor::access_t const entry =
|
|
||||||
Small_page::create(flags, pa);
|
|
||||||
|
|
||||||
/* check if we can we write to the targeted entry */
|
|
||||||
if (Descriptor::valid(_entries[i]))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* It's possible that multiple threads fault at the
|
|
||||||
* same time on the same translation, thus we need
|
|
||||||
* this check.
|
|
||||||
*/
|
|
||||||
if (_entries[i] == entry) return;
|
|
||||||
|
|
||||||
/* never modify existing translations */
|
|
||||||
PDBG("Couldn't override entry");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
/* override table entry with new descriptor value */
|
|
||||||
_entries[i] = entry;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PDBG("Translation size not supported");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove translations that overlap with a given virtual region
|
|
||||||
*
|
|
||||||
* \param vo region offset within the tables virtual region
|
|
||||||
* \param size region size
|
|
||||||
*/
|
|
||||||
void remove_region(addr_t vo, size_t const size)
|
|
||||||
{
|
|
||||||
addr_t const ve = vo + size;
|
|
||||||
unsigned i;
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (vo >= ve) { return; }
|
|
||||||
if (_index_by_vo(i, vo)) { return; }
|
|
||||||
addr_t next_vo;
|
|
||||||
switch (Descriptor::type(_entries[i])) {
|
|
||||||
|
|
||||||
case Descriptor::FAULT: {
|
|
||||||
|
|
||||||
vo &= Fault::VIRT_BASE_MASK;
|
|
||||||
next_vo = vo + Fault::VIRT_SIZE;
|
|
||||||
break; }
|
|
||||||
|
|
||||||
case Descriptor::SMALL_PAGE: {
|
|
||||||
|
|
||||||
vo &= Small_page::VIRT_BASE_MASK;
|
|
||||||
Descriptor::invalidate(_entries[i]);
|
|
||||||
next_vo = vo + Small_page::VIRT_SIZE;
|
|
||||||
break; }
|
|
||||||
}
|
|
||||||
if (next_vo < vo) { return; }
|
|
||||||
vo = next_vo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does this table solely contain invalid entries
|
|
||||||
*/
|
|
||||||
bool empty()
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i <= MAX_INDEX; i++) {
|
|
||||||
if (Descriptor::valid(_entries[i])) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get next translation size log2 by area constraints
|
|
||||||
*
|
|
||||||
* \param vo virtual offset within this table
|
|
||||||
* \param s area size
|
|
||||||
*/
|
|
||||||
static unsigned
|
|
||||||
translation_size_l2(addr_t const vo, size_t const s)
|
|
||||||
{
|
|
||||||
off_t const o = vo & Small_page::VIRT_OFFSET_MASK;
|
|
||||||
if (!o && s >= Small_page::VIRT_SIZE)
|
|
||||||
return Small_page::VIRT_SIZE_LOG2;
|
|
||||||
PDBG("Insufficient alignment or size");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
} __attribute__((aligned(1<<Page_table::ALIGNM_LOG2)));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* First level translation table
|
|
||||||
*/
|
|
||||||
class Section_table
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
_16KB_LOG2 = 14,
|
|
||||||
_1MB_LOG2 = 20,
|
|
||||||
_16MB_LOG2 = 24,
|
|
||||||
|
|
||||||
DOMAIN = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum {
|
|
||||||
SIZE_LOG2 = _16KB_LOG2,
|
|
||||||
SIZE = 1 << SIZE_LOG2,
|
|
||||||
ALIGNM_LOG2 = SIZE_LOG2,
|
|
||||||
|
|
||||||
VIRT_SIZE_LOG2 = _1MB_LOG2,
|
|
||||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
|
||||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1),
|
|
||||||
|
|
||||||
MAX_COSTS_PER_TRANSLATION = sizeof(Page_table),
|
|
||||||
|
|
||||||
MAX_PAGE_SIZE_LOG2 = 20,
|
|
||||||
MIN_PAGE_SIZE_LOG2 = 12,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A first level translation descriptor
|
|
||||||
*/
|
|
||||||
struct Descriptor : Register<32>
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Descriptor types
|
|
||||||
*/
|
|
||||||
enum Type { FAULT, PAGE_TABLE, SECTION };
|
|
||||||
|
|
||||||
struct Type_0 : Bitfield<0, 2> { };
|
|
||||||
struct Type_1_0 : Bitfield<1, 1> { };
|
|
||||||
struct Type_1_1 : Bitfield<18, 1> { };
|
|
||||||
struct Type_1 : Bitset_2<Type_1_0, Type_1_1> { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get descriptor type of 'v'
|
|
||||||
*/
|
|
||||||
static Type type(access_t const v)
|
|
||||||
{
|
|
||||||
access_t const t0 = Type_0::get(v);
|
|
||||||
if (t0 == 0) { return FAULT; }
|
|
||||||
if (t0 == 1) { return PAGE_TABLE; }
|
|
||||||
access_t const t1 = Type_1::get(v);
|
|
||||||
if (t1 == 1) { return SECTION; }
|
|
||||||
return FAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set descriptor type of 'v'
|
|
||||||
*/
|
|
||||||
static void type(access_t & v, Type const t)
|
|
||||||
{
|
|
||||||
switch (t) {
|
|
||||||
case FAULT:
|
|
||||||
Type_0::set(v, 0);
|
|
||||||
return;
|
|
||||||
case PAGE_TABLE:
|
|
||||||
Type_0::set(v, 1);
|
|
||||||
return;
|
|
||||||
case SECTION:
|
|
||||||
Type_1::set(v, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invalidate descriptor 'v'
|
|
||||||
*/
|
|
||||||
static void invalidate(access_t & v) { type(v, FAULT); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return if descriptor 'v' is valid
|
|
||||||
*/
|
|
||||||
static bool valid(access_t & v) { return type(v) != FAULT; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an untranslated virtual region
|
|
||||||
*/
|
|
||||||
struct Fault : Descriptor
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
VIRT_SIZE_LOG2 = _1MB_LOG2,
|
|
||||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
|
||||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Link to a second level translation table
|
|
||||||
*/
|
|
||||||
struct Page_table_descriptor : Descriptor
|
|
||||||
{
|
|
||||||
struct Domain : Bitfield<5, 4> { }; /* domain */
|
|
||||||
struct Pa_31_10 : Bitfield<10, 22> { }; /* physical base */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compose descriptor value
|
|
||||||
*/
|
|
||||||
static access_t create(Page_table * const pt)
|
|
||||||
{
|
|
||||||
access_t v = Domain::bits(DOMAIN) |
|
|
||||||
Pa_31_10::masked((addr_t)pt);
|
|
||||||
Descriptor::type(v, Descriptor::PAGE_TABLE);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Section translation descriptor
|
|
||||||
*/
|
|
||||||
struct Section : Descriptor
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
VIRT_SIZE_LOG2 = _1MB_LOG2,
|
|
||||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
|
||||||
VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1,
|
|
||||||
VIRT_BASE_MASK = ~(VIRT_OFFSET_MASK),
|
|
||||||
};
|
|
||||||
|
|
||||||
struct B : Bitfield<2, 1> { }; /* mem. region attr. */
|
|
||||||
struct C : Bitfield<3, 1> { }; /* mem. region attr. */
|
|
||||||
struct Xn : Bitfield<4, 1> { }; /* execute never bit */
|
|
||||||
struct Domain : Bitfield<5, 4> { }; /* domain */
|
|
||||||
struct Ap_0 : Bitfield<10, 2> { }; /* access permission */
|
|
||||||
struct Tex : Bitfield<12, 3> { }; /* mem. region attr. */
|
|
||||||
struct Ap_1 : Bitfield<15, 1> { }; /* access permission */
|
|
||||||
struct S : Bitfield<16, 1> { }; /* shared */
|
|
||||||
struct Ng : Bitfield<17, 1> { }; /* not global */
|
|
||||||
struct Pa_31_20 : Bitfield<20, 12> { }; /* physical base */
|
|
||||||
|
|
||||||
struct Ap : Bitset_2<Ap_0, Ap_1> { }; /* access permission */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compose descriptor value
|
|
||||||
*/
|
|
||||||
static access_t create(Page_flags const & flags,
|
|
||||||
addr_t const pa)
|
|
||||||
{
|
|
||||||
access_t v = access_permission_bits<Section>(flags);
|
|
||||||
v |= memory_region_attr<Section>(flags);
|
|
||||||
v |= Domain::bits(DOMAIN);
|
|
||||||
v |= S::bits(1);
|
|
||||||
v |= Ng::bits(!flags.global);
|
|
||||||
v |= Pa_31_20::masked(pa);
|
|
||||||
Descriptor::type(v, Descriptor::SECTION);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/* table payload, must be the first member of this class */
|
|
||||||
Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)];
|
|
||||||
|
|
||||||
enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get entry index by virtual offset
|
|
||||||
*
|
|
||||||
* \param i is overridden with the resulting index
|
|
||||||
* \param vo offset within the virtual region represented
|
|
||||||
* by this table
|
|
||||||
*
|
|
||||||
* \retval 0 on success
|
|
||||||
* \retval <0 if virtual offset couldn't be resolved,
|
|
||||||
* in this case 'i' reside invalid
|
|
||||||
*/
|
|
||||||
int _index_by_vo(unsigned & i, addr_t const vo) const
|
|
||||||
{
|
|
||||||
if (vo > max_virt_offset()) return -1;
|
|
||||||
i = vo >> Section::VIRT_SIZE_LOG2;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Placement new
|
|
||||||
*/
|
|
||||||
void * operator new (size_t, void * p) { return p; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Section_table()
|
|
||||||
{
|
|
||||||
/* check for appropriate positioning of the table */
|
|
||||||
if (!aligned((addr_t)this, ALIGNM_LOG2)
|
|
||||||
|| (addr_t)this != (addr_t)_entries)
|
|
||||||
{
|
|
||||||
PDBG("Insufficient table alignment");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
/* start with an empty table */
|
|
||||||
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
|
||||||
Descriptor::invalidate(_entries[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum virtual offset that can be translated by this table
|
|
||||||
*/
|
|
||||||
static addr_t max_virt_offset()
|
|
||||||
{
|
|
||||||
return (MAX_INDEX << Section::VIRT_SIZE_LOG2)
|
|
||||||
+ (Section::VIRT_SIZE - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert one atomic translation into this table
|
|
||||||
*
|
|
||||||
* \param ST platform specific section-table type
|
|
||||||
* \param st platform specific section 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_log2 size log2 of the translated region
|
|
||||||
* \param flags mapping flags
|
|
||||||
* \param extra_space If > 0, it must point to a portion of
|
|
||||||
* size-aligned memory space wich may be used
|
|
||||||
* furthermore by the table for the incurring
|
|
||||||
* administrative costs of the translation.
|
|
||||||
* To determine the amount of additionally
|
|
||||||
* needed memory one can instrument this
|
|
||||||
* method with 'extra_space' set to 0.
|
|
||||||
* The so donated memory may be regained by
|
|
||||||
* using the method 'regain_memory'.
|
|
||||||
*
|
|
||||||
* \retval 0 translation successfully inserted
|
|
||||||
* \retval >0 Translation not inserted, the return value
|
|
||||||
* is the size log2 of additional size-aligned
|
|
||||||
* space that is needed to do the translation.
|
|
||||||
* This occurs solely when 'extra_space' is 0.
|
|
||||||
*
|
|
||||||
* This method overrides an existing translation in case that it
|
|
||||||
* spans the the same virtual range and is not a link to another
|
|
||||||
* table level.
|
|
||||||
*/
|
|
||||||
template <typename ST>
|
|
||||||
size_t insert_translation(addr_t const vo, addr_t const pa,
|
|
||||||
size_t const size_log2,
|
|
||||||
Page_flags const & flags,
|
|
||||||
ST * const st,
|
|
||||||
void * const extra_space = 0)
|
|
||||||
{
|
|
||||||
typedef typename ST::Section Section;
|
|
||||||
typedef typename ST::Page_table_descriptor Page_table_descriptor;
|
|
||||||
|
|
||||||
/* validate virtual address */
|
|
||||||
unsigned i;
|
|
||||||
if (_index_by_vo (i, vo)) {
|
|
||||||
PDBG("Invalid virtual offset");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
/* select descriptor type by translation size */
|
|
||||||
if (size_log2 < Section::VIRT_SIZE_LOG2)
|
|
||||||
{
|
|
||||||
/* check if an appropriate page table already exists */
|
|
||||||
Page_table * pt;
|
|
||||||
if (Descriptor::type(_entries[i]) == Descriptor::PAGE_TABLE) {
|
|
||||||
pt = (Page_table *)(addr_t)
|
|
||||||
Page_table_descriptor::Pa_31_10::masked(_entries[i]);
|
|
||||||
}
|
|
||||||
/* check if we have enough memory for the page table */
|
|
||||||
else if (extra_space)
|
|
||||||
{
|
|
||||||
/* check if we can write to the targeted entry */
|
|
||||||
if (Descriptor::valid(_entries[i])) {
|
|
||||||
PDBG ("Couldn't override entry");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
/* create and link page table */
|
|
||||||
pt = new (extra_space) Page_table();
|
|
||||||
_entries[i] = Page_table_descriptor::create(pt, st);
|
|
||||||
}
|
|
||||||
/* request additional memory to create a page table */
|
|
||||||
else return Page_table::SIZE_LOG2;
|
|
||||||
|
|
||||||
/* insert translation */
|
|
||||||
pt->insert_translation(vo - Section::Pa_31_20::masked(vo),
|
|
||||||
pa, size_log2, flags);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (size_log2 == Section::VIRT_SIZE_LOG2)
|
|
||||||
{
|
|
||||||
/* compose section descriptor */
|
|
||||||
Descriptor::access_t const entry =
|
|
||||||
Section::create(flags, pa, st);
|
|
||||||
|
|
||||||
/* check if we can we write to the targeted entry */
|
|
||||||
if (Descriptor::valid(_entries[i]))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* It's possible that multiple threads fault at the
|
|
||||||
* same time on the same translation, thus we need
|
|
||||||
* this check.
|
|
||||||
*/
|
|
||||||
if (_entries[i] == entry) return 0;
|
|
||||||
|
|
||||||
/* never modify existing translations */
|
|
||||||
PDBG("Couldn't override entry");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
/* override the table entry */
|
|
||||||
_entries[i] = entry;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
PDBG("Translation size not supported");
|
|
||||||
while (1) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove translations that overlap with a given virtual region
|
|
||||||
*
|
|
||||||
* \param vo region offset within the tables virtual region
|
|
||||||
* \param size region size
|
|
||||||
*/
|
|
||||||
void remove_region(addr_t vo, size_t const size)
|
|
||||||
{
|
|
||||||
addr_t const ve = vo + size;
|
|
||||||
unsigned i;
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (vo >= ve) { return; }
|
|
||||||
if (_index_by_vo(i, vo)) { return; }
|
|
||||||
addr_t next_vo;
|
|
||||||
switch (Descriptor::type(_entries[i])) {
|
|
||||||
|
|
||||||
case Descriptor::FAULT: {
|
|
||||||
|
|
||||||
vo &= Fault::VIRT_BASE_MASK;
|
|
||||||
next_vo = vo + Fault::VIRT_SIZE;
|
|
||||||
break; }
|
|
||||||
|
|
||||||
case Descriptor::PAGE_TABLE: {
|
|
||||||
|
|
||||||
typedef Page_table_descriptor Ptd;
|
|
||||||
typedef Page_table Pt;
|
|
||||||
|
|
||||||
vo &= Pt::VIRT_BASE_MASK;
|
|
||||||
Pt * const pt = (Pt *)Ptd::Pa_31_10::masked(_entries[i]);
|
|
||||||
addr_t const pt_vo = vo - Section::Pa_31_20::masked(vo);
|
|
||||||
pt->remove_region(pt_vo, ve - vo);
|
|
||||||
next_vo = vo + Pt::VIRT_SIZE;
|
|
||||||
break; }
|
|
||||||
|
|
||||||
case Descriptor::SECTION: {
|
|
||||||
|
|
||||||
vo &= Section::VIRT_BASE_MASK;
|
|
||||||
Descriptor::invalidate(_entries[i]);
|
|
||||||
next_vo = vo + Section::VIRT_SIZE;
|
|
||||||
break; }
|
|
||||||
}
|
|
||||||
if (next_vo < vo) { return; }
|
|
||||||
vo = next_vo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get base address for hardware table walk
|
|
||||||
*/
|
|
||||||
addr_t base() const { return (addr_t)_entries; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a portion of memory that is no longer used by this table
|
|
||||||
*
|
|
||||||
* \param base base of regained mem portion if method returns 1
|
|
||||||
* \param s size of regained mem portion if method returns 1
|
|
||||||
*
|
|
||||||
* \retval 1 successfully regained memory
|
|
||||||
* \retval 0 no more memory to regain
|
|
||||||
*/
|
|
||||||
bool regain_memory (void * & base, size_t & s)
|
|
||||||
{
|
|
||||||
/* walk through all entries */
|
|
||||||
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
|
||||||
{
|
|
||||||
if (Descriptor::type(_entries[i]) == Descriptor::PAGE_TABLE)
|
|
||||||
{
|
|
||||||
Page_table * const pt = (Page_table *)
|
|
||||||
(addr_t)Page_table_descriptor::Pa_31_10::masked(_entries[i]);
|
|
||||||
if (pt->empty())
|
|
||||||
{
|
|
||||||
/* we've found an useless page table */
|
|
||||||
Descriptor::invalidate(_entries[i]);
|
|
||||||
base = (void *)pt;
|
|
||||||
s = sizeof(Page_table);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get next translation size log2 by area constraints
|
|
||||||
*
|
|
||||||
* \param vo virtual offset within this table
|
|
||||||
* \param s area size
|
|
||||||
*/
|
|
||||||
static unsigned
|
|
||||||
translation_size_l2(addr_t const vo, size_t const s)
|
|
||||||
{
|
|
||||||
off_t const o = vo & Section::VIRT_OFFSET_MASK;
|
|
||||||
if (!o && s >= Section::VIRT_SIZE)
|
|
||||||
return Section::VIRT_SIZE_LOG2;
|
|
||||||
return Page_table::translation_size_l2(o, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert translations for given area, do not permit displacement
|
|
||||||
*
|
|
||||||
* \param vo virtual offset within this table
|
|
||||||
* \param s area size
|
|
||||||
* \param flags mapping flags
|
|
||||||
*/
|
|
||||||
template <typename ST>
|
|
||||||
void map_core_area(addr_t vo, size_t s, bool io_mem, ST * st)
|
|
||||||
{
|
|
||||||
/* initialize parameters */
|
|
||||||
Page_flags const flags = Page_flags::map_core_area(io_mem);
|
|
||||||
unsigned tsl2 = translation_size_l2(vo, s);
|
|
||||||
size_t ts = 1 << tsl2;
|
|
||||||
|
|
||||||
/* walk through the area and map all offsets */
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
/* map current offset without displacement */
|
|
||||||
if(st->insert_translation(vo, vo, tsl2, flags)) {
|
|
||||||
PDBG("Displacement not permitted");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* update parameters for next round or exit */
|
|
||||||
vo += ts;
|
|
||||||
s = ts < s ? s - ts : 0;
|
|
||||||
if (!s) return;
|
|
||||||
tsl2 = translation_size_l2(vo, s);
|
|
||||||
ts = 1 << tsl2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} __attribute__((aligned(1<<Section_table::ALIGNM_LOG2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _TLB__ARM_H_ */
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief TLB driver for core
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2012-02-22
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _TLB__ARM_V6_H_
|
|
||||||
#define _TLB__ARM_V6_H_
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <tlb/arm.h>
|
|
||||||
|
|
||||||
namespace Arm_v6
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* First level translation table
|
|
||||||
*/
|
|
||||||
class Section_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Arm_v6::Section_table : public Arm::Section_table
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
typedef Arm::Section_table Base;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Link to second level translation-table
|
|
||||||
*/
|
|
||||||
struct Page_table_descriptor : Base::Page_table_descriptor
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Compose descriptor value
|
|
||||||
*/
|
|
||||||
static access_t create(Arm::Page_table * const pt, Section_table *)
|
|
||||||
{
|
|
||||||
return Base::Page_table_descriptor::create(pt);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Section translation descriptor
|
|
||||||
*/
|
|
||||||
struct Section : Base::Section
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Compose descriptor value
|
|
||||||
*/
|
|
||||||
static access_t create(Page_flags const & flags,
|
|
||||||
addr_t const pa, Section_table *)
|
|
||||||
{
|
|
||||||
return Base::Section::create(flags, pa);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert one atomic translation into this table
|
|
||||||
*
|
|
||||||
* For details see 'Base::insert_translation'
|
|
||||||
*/
|
|
||||||
size_t insert_translation(addr_t const vo, addr_t const pa,
|
|
||||||
size_t const size_l2,
|
|
||||||
Page_flags const & f,
|
|
||||||
void * const p = 0)
|
|
||||||
{
|
|
||||||
return Base::insert_translation(vo, pa, size_l2, f, this, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert translations for given area, do not permit displacement
|
|
||||||
*
|
|
||||||
* \param vo virtual offset within this table
|
|
||||||
* \param s area size
|
|
||||||
* \param io_mem wether the area maps MMIO
|
|
||||||
*/
|
|
||||||
void map_core_area(addr_t vo, size_t s, bool const io_mem)
|
|
||||||
{
|
|
||||||
Base::map_core_area(vo, s, io_mem, this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename T::access_t
|
|
||||||
Arm::memory_region_attr(Page_flags const & flags)
|
|
||||||
{
|
|
||||||
typedef typename T::Tex Tex;
|
|
||||||
typedef typename T::C C;
|
|
||||||
typedef typename T::B B;
|
|
||||||
if(flags.device) { return 0; }
|
|
||||||
if(flags.cacheable) { return Tex::bits(5) | B::bits(1); }
|
|
||||||
return Tex::bits(6) | C::bits(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _TLB__ARM_V6_H_ */
|
|
@ -1,134 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief TLB driver for core
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2012-02-22
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _TLB__ARM_V7_H_
|
|
||||||
#define _TLB__ARM_V7_H_
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <tlb/arm.h>
|
|
||||||
#include <processor_driver.h>
|
|
||||||
|
|
||||||
namespace Arm_v7
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* First level translation table
|
|
||||||
*/
|
|
||||||
class Section_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
class Arm_v7::Section_table : public Arm::Section_table
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
typedef Arm::Section_table Base;
|
|
||||||
typedef Genode::addr_t addr_t;
|
|
||||||
typedef Genode::size_t size_t;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Link to second level translation-table
|
|
||||||
*/
|
|
||||||
struct Page_table_descriptor : Base::Page_table_descriptor
|
|
||||||
{
|
|
||||||
struct Ns : Bitfield<3, 1> { }; /* non-secure bit */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compose descriptor value
|
|
||||||
*/
|
|
||||||
static access_t create(Arm::Page_table * const pt,
|
|
||||||
Section_table * const st)
|
|
||||||
{
|
|
||||||
access_t const ns = Ns::bits(!st->secure());
|
|
||||||
return Base::Page_table_descriptor::create(pt) | ns;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Section translation descriptor
|
|
||||||
*/
|
|
||||||
struct Section : Base::Section
|
|
||||||
{
|
|
||||||
struct Ns : Bitfield<19, 1> { }; /* non-secure bit */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compose descriptor value
|
|
||||||
*/
|
|
||||||
static access_t create(Page_flags const & flags,
|
|
||||||
addr_t const pa, Section_table * const st)
|
|
||||||
{
|
|
||||||
access_t const ns = Ns::bits(!st->secure());
|
|
||||||
return Base::Section::create(flags, pa) | ns;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/* if this table is dedicated to secure mode or to non-secure mode */
|
|
||||||
bool const _secure;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Section_table() : _secure(Processor_driver::secure_mode()) { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert one atomic translation into this table
|
|
||||||
*
|
|
||||||
* For details see 'Base::insert_translation'
|
|
||||||
*/
|
|
||||||
size_t insert_translation(addr_t const vo, addr_t const pa,
|
|
||||||
size_t const size_log2,
|
|
||||||
Page_flags const & flags,
|
|
||||||
void * const p = 0)
|
|
||||||
{
|
|
||||||
return Base::insert_translation(vo, pa, size_log2, flags, this, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert translations for given area, do not permit displacement
|
|
||||||
*
|
|
||||||
* \param vo virtual offset within this table
|
|
||||||
* \param s area size
|
|
||||||
* \param io_mem wether the area maps MMIO
|
|
||||||
*/
|
|
||||||
void map_core_area(addr_t vo, size_t s, bool const io_mem)
|
|
||||||
{
|
|
||||||
Base::map_core_area(vo, s, io_mem, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************
|
|
||||||
** Accessors **
|
|
||||||
***************/
|
|
||||||
|
|
||||||
bool secure() const { return _secure; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static typename T::access_t
|
|
||||||
Arm::memory_region_attr(Page_flags const & flags)
|
|
||||||
{
|
|
||||||
typedef typename T::Tex Tex;
|
|
||||||
typedef typename T::C C;
|
|
||||||
typedef typename T::B B;
|
|
||||||
if (flags.device) { return Tex::bits(2); }
|
|
||||||
if (flags.cacheable) { return Tex::bits(5) | B::bits(1); }
|
|
||||||
return Tex::bits(6) | C::bits(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _TLB__ARM_V7_H_ */
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Translation lookaside buffer
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2012-04-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _VEA9X4__TLB_H_
|
|
||||||
#define _VEA9X4__TLB_H_
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <board.h>
|
|
||||||
#include <tlb/arm_v7.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
class Tlb : public Arm_v7::Section_table { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation lookaside buffer of core
|
|
||||||
*/
|
|
||||||
class Core_tlb : public Tlb
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor - ensures that core never gets a pagefault
|
|
||||||
*/
|
|
||||||
Core_tlb()
|
|
||||||
{
|
|
||||||
map_core_area(Board::RAM_0_BASE, Board::RAM_0_SIZE, 0);
|
|
||||||
map_core_area(Board::RAM_1_BASE, Board::RAM_1_SIZE, 0);
|
|
||||||
map_core_area(Board::RAM_2_BASE, Board::RAM_2_SIZE, 0);
|
|
||||||
map_core_area(Board::RAM_3_BASE, Board::RAM_3_SIZE, 0);
|
|
||||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
|
||||||
map_core_area(Board::MMIO_1_BASE, Board::MMIO_1_SIZE, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _VEA9X4__TLB_H_ */
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Translation lookaside buffer
|
|
||||||
* \author Martin Stein
|
|
||||||
* \author Stefan Kalkowski
|
|
||||||
* \date 2012-04-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 _VEA9X4__TLB_H_
|
|
||||||
#define _VEA9X4__TLB_H_
|
|
||||||
|
|
||||||
#include <drivers/trustzone.h>
|
|
||||||
|
|
||||||
/* core includes */
|
|
||||||
#include <board.h>
|
|
||||||
#include <tlb/arm_v7.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
class Tlb : public Arm_v7::Section_table { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation lookaside buffer of core
|
|
||||||
*/
|
|
||||||
class Core_tlb : public Tlb
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor - ensures that core never gets a pagefault
|
|
||||||
*/
|
|
||||||
Core_tlb()
|
|
||||||
{
|
|
||||||
map_core_area(Trustzone::SECURE_RAM_BASE, Trustzone::SECURE_RAM_SIZE, 0);
|
|
||||||
map_core_area(Board::MMIO_0_BASE, Board::MMIO_0_SIZE, 1);
|
|
||||||
map_core_area(Board::MMIO_1_BASE, Board::MMIO_1_SIZE, 1);
|
|
||||||
map_core_area(Trustzone::VM_STATE_BASE, Trustzone::VM_STATE_SIZE, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _VEA9X4__TLB_H_ */
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user