sel4: bootstrap of init and page-fault handling

This commit is contained in:
Norman Feske 2015-05-12 12:48:03 +02:00 committed by Christian Helmuth
parent 691f0eaae7
commit 5a05521e0f
17 changed files with 692 additions and 208 deletions

View File

@ -0,0 +1,37 @@
/*
* \brief Connection to PD service
* \author Norman Feske
* \date 2008-08-22
*/
/*
* Copyright (C) 2008-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 _INCLUDE__PD_SESSION__CONNECTION_H_
#define _INCLUDE__PD_SESSION__CONNECTION_H_
#include <pd_session/client.h>
#include <base/connection.h>
namespace Genode { struct Pd_connection; }
struct Genode::Pd_connection : Connection<Pd_session>, Pd_session_client
{
/**
* Constructor
*
* \param label session label
*/
Pd_connection(char const *label = "", Native_pd_args const *pd_args = 0)
:
Connection<Pd_session>(session("ram_quota=64K, label=\"%s\"", label)),
Pd_session_client(cap())
{ }
};
#endif /* _INCLUDE__PD_SESSION__CONNECTION_H_ */

View File

@ -6,7 +6,7 @@
LIBS += cxx startup syscall
SRC_CC += ipc/ipc.cc ipc/pager.cc
SRC_CC += ipc/ipc.cc
SRC_CC += avl_tree/avl_tree.cc
SRC_CC += allocator/slab.cc
SRC_CC += allocator/allocator_avl.cc
@ -18,7 +18,6 @@ SRC_CC += elf/elf_binary.cc
SRC_CC += lock/lock.cc
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
SRC_CC += server/server.cc server/common.cc
SRC_CC += pager/pager.cc pager/common.cc
SRC_CC += thread/thread.cc
SRC_CC += thread/trace.cc
SRC_CC += thread/myself.cc

View File

@ -29,7 +29,8 @@ SRC_CC += \
core_mem_alloc.cc \
dump_alloc.cc \
context_area.cc \
capability_space.cc
capability_space.cc \
pager.cc
LIBS += core_printf base-common syscall

View File

@ -1,44 +0,0 @@
/*
* \brief Pager support for seL4
* \author Norman Feske
* \date 2014-10-14
*/
/*
* 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/ipc_pager.h>
#include <base/printf.h>
using namespace Genode;
/***************
** IPC pager **
***************/
void Ipc_pager::wait_for_fault()
{
PDBG("not implemented");
}
void Ipc_pager::reply_and_wait_for_fault()
{
PDBG("not implemented");
}
void Ipc_pager::acknowledge_wakeup()
{
PDBG("not implemented");
}
Ipc_pager::Ipc_pager() { }

View File

@ -1,61 +0,0 @@
/*
* \brief Pager framework
* \author Norman Feske
* \date 2015-05-01
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/pager.h>
#include <base/sleep.h>
using namespace Genode;
/**********************
** Pager activation **
**********************/
void Pager_activation_base::entry()
{
Ipc_pager pager;
_cap = pager;
_cap_valid.unlock();
while (1) {
PDBG("not implemented");
sleep_forever();
}
}
/**********************
** Pager entrypoint **
**********************/
Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a)
: _activation(a)
{ _activation->ep(this); }
void Pager_entrypoint::dissolve(Pager_object *obj)
{
remove_locked(obj);
}
Pager_capability Pager_entrypoint::manage(Pager_object *obj)
{
/* return invalid capability if no activation is present */
if (!_activation) return Pager_capability();
PDBG("not implemented");
return Pager_capability();
}

View File

@ -0,0 +1,26 @@
/*
* \brief Interface for mapping memory to the VM space of a pager object
* \author Norman Feske
* \date 2015-05-12
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _CORE__INCLUDE__INSTALL_MAPPING_H_
#define _CORE__INCLUDE__INSTALL_MAPPING_H_
/* Genode includes */
#include <base/ipc_pager.h>
#include <base/pager.h>
namespace Genode {
void install_mapping(Mapping const &mapping, unsigned long pager_object_badge);
}
#endif /* _CORE__INCLUDE__INSTALL_MAPPING_H_ */

View File

@ -51,6 +51,13 @@ namespace Kernel_object {
};
struct Page_directory
{
enum { SEL4_TYPE = seL4_IA32_PageDirectoryObject, SIZE_LOG2 = 12 };
static char const *name() { return "page directory"; }
};
/**
* Create kernel object from untyped memory
*

View File

@ -19,7 +19,7 @@
/* core includes */
#include <util.h>
#include <platform_generic.h>
#include <platform.h>
namespace Genode {

View File

@ -20,6 +20,7 @@
/* core includes */
#include <platform_thread.h>
#include <address_space.h>
#include <vm_space.h>
namespace Genode { class Platform_pd; }
@ -27,6 +28,38 @@ namespace Genode { class Platform_pd; }
class Genode::Platform_pd : public Address_space
{
private:
unsigned const _id; /* used as index in top-level CNode */
Page_table_registry _page_table_registry;
unsigned const _vm_pad_cnode_sel;
unsigned const _vm_cnode_sel;
unsigned const _page_directory_sel;
Untyped_address _init_page_directory();
Untyped_address const _page_directory = _init_page_directory();
Vm_space _vm_space;
unsigned const _cspace_cnode_sel;
Cnode _cspace_cnode;
enum { CSPACE_SIZE_LOG2 = 12 };
/*
* Allocator for core-managed selectors within the PD's CSpace
*/
enum { NUM_CORE_MANAGED_SELECTORS_LOG2 = 10 };
struct Sel_alloc : Bit_allocator<1 << NUM_CORE_MANAGED_SELECTORS_LOG2> { };
Sel_alloc _sel_alloc;
Lock _sel_alloc_lock;
public:
/**
@ -66,6 +99,23 @@ class Genode::Platform_pd : public Address_space
*****************************/
void flush(addr_t, size_t) { PDBG("not implemented"); }
/*****************************
** seL4-specific interface **
*****************************/
unsigned alloc_sel();
void free_sel(unsigned sel);
Cnode &cspace_cnode() { return _cspace_cnode; }
unsigned page_directory_sel() const { return _page_directory_sel; }
size_t cspace_size_log2() { return CSPACE_SIZE_LOG2; }
void install_mapping(Mapping const &mapping);
};
#endif /* _CORE__INCLUDE__PLATFORM_PD_H_ */

View File

@ -18,9 +18,13 @@
#include <base/pager.h>
#include <base/thread_state.h>
#include <base/native_types.h>
#include <util/string.h>
#include <base/ipc_pager.h>
/* core includes */
#include <address_space.h>
#include <thread_sel4.h>
#include <install_mapping.h>
namespace Genode {
@ -29,17 +33,27 @@ namespace Genode {
}
class Genode::Platform_thread
class Genode::Platform_thread : public List<Platform_thread>::Element
{
private:
Pager_object *_pager = nullptr;
Weak_ptr<Address_space> _address_space;
String<128> _name;
Thread_info _info;
unsigned const _pager_obj_sel;
/*
* Allocated when the thread is started
*/
unsigned _fault_handler_sel = 0;
friend class Platform_pd;
Platform_pd *_pd = nullptr;
public:
/**
@ -114,11 +128,7 @@ class Genode::Platform_thread
/**
* Return identification of thread when faulting
*/
unsigned long pager_object_badge() const
{
PDBG("not implemented");
return 0;
}
unsigned long pager_object_badge() const { return _pager_obj_sel; }
/**
* Set the executing CPU for this thread
@ -139,6 +149,15 @@ class Genode::Platform_thread
* Get thread name
*/
const char *name() const { return "noname"; }
/*****************************
** seL4-specific interface **
*****************************/
unsigned tcb_sel() const { return _info.tcb_sel; }
void install_mapping(Mapping const &mapping);
};
#endif /* _CORE__INCLUDE__PLATFORM_THREAD_H_ */

View File

@ -0,0 +1,110 @@
/*
* \brief Utilities fo thread creation on seL4
* \author Norman Feske
* \date 2015-05-12
*
* This file is used by both the core-specific implementation of the Thread API
* and the platform-thread implementation for managing threads outside of core.
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _CORE__INCLUDE__THREAD_SEL4_H_
#define _CORE__INCLUDE__THREAD_SEL4_H_
/* Genode includes */
#include <base/printf.h>
/* base-internal includes */
#include <internal/assert.h>
/* core includes */
#include <map_local.h>
#include <kernel_object.h>
namespace Genode {
struct Thread_info
{
unsigned tcb_sel = 0;
unsigned ep_sel = 0;
addr_t ipc_buffer_phys = 0;
Thread_info() { }
inline void init(addr_t const utcb_virt_addr);
};
/**
* Set register values for the instruction pointer and stack pointer and
* start the seL4 thread
*/
static inline void start_sel4_thread(unsigned tcb_sel, addr_t ip, addr_t sp);
};
void Genode::Thread_info::init(addr_t const utcb_virt_addr)
{
Platform &platform = *platform_specific();
Range_allocator &phys_alloc = *platform.ram_alloc();
/* create IPC buffer of one page */
size_t const ipc_buffer_size_log2 = get_page_size_log2();
Untyped_address ipc_buffer =
Untyped_memory::alloc_log2(phys_alloc, ipc_buffer_size_log2);
ipc_buffer_phys = ipc_buffer.phys();
Untyped_memory::convert_to_page_frames(ipc_buffer.phys(), 1);
/* allocate TCB within core's CNode */
tcb_sel = platform.alloc_core_sel();
Kernel_object::create<Kernel_object::Tcb>(phys_alloc,
platform.core_cnode().sel(),
tcb_sel);
/* allocate synchronous endpoint within core's CNode */
ep_sel = platform.alloc_core_sel();
Kernel_object::create<Kernel_object::Endpoint>(phys_alloc,
platform.core_cnode().sel(),
ep_sel);
/* assign IPC buffer to thread */
{
/* determine page frame selector of the allocated IPC buffer */
unsigned ipc_buffer_sel = Untyped_memory::frame_sel(ipc_buffer.phys());
int const ret = seL4_TCB_SetIPCBuffer(tcb_sel, utcb_virt_addr,
ipc_buffer_sel);
ASSERT(ret == 0);
}
/* set scheduling priority */
enum { PRIORITY_MAX = 0xff };
seL4_TCB_SetPriority(tcb_sel, PRIORITY_MAX);
}
void Genode::start_sel4_thread(unsigned tcb_sel, addr_t ip, addr_t sp)
{
/* set register values for the instruction pointer and stack pointer */
seL4_UserContext regs;
Genode::memset(&regs, 0, sizeof(regs));
size_t const num_regs = sizeof(regs)/sizeof(seL4_Word);
regs.eip = ip;
regs.esp = sp;
regs.gs = IPCBUF_GDT_SELECTOR;
int const ret = seL4_TCB_WriteRegisters(tcb_sel, false, 0, num_regs, &regs);
ASSERT(ret == 0);
seL4_TCB_Resume(tcb_sel);
}
#endif /* _CORE__INCLUDE__THREAD_SEL4_H_ */

View File

@ -31,6 +31,7 @@ class Genode::Vm_space
Page_table_registry &_page_table_registry;
unsigned const _id;
unsigned const _pd_sel;
Range_allocator &_phys_alloc;
@ -57,6 +58,8 @@ class Genode::Vm_space
*/
Bit_allocator<1UL << NUM_VM_SEL_LOG2> _sel_alloc;
Lock _lock;
/**
* Return selector for a capability slot within '_vm_cnode'
*/
@ -83,7 +86,7 @@ class Genode::Vm_space
*/
{
seL4_IA32_Page const service = _idx_to_sel(pte_idx);
seL4_IA32_PageDirectory const pd = seL4_CapInitThreadPD;
seL4_IA32_PageDirectory const pd = _pd_sel;
seL4_Word const vaddr = to_virt;
seL4_CapRights const rights = seL4_AllRights;
seL4_IA32_VMAttributes const attr = seL4_IA32_Default_VMAttributes;
@ -110,7 +113,7 @@ class Genode::Vm_space
void _map_page_table(unsigned pt_sel, addr_t to_virt)
{
seL4_IA32_PageTable const service = pt_sel;
seL4_IA32_PageDirectory const pd = seL4_CapInitThreadPD;
seL4_IA32_PageDirectory const pd = _pd_sel;
seL4_Word const vaddr = to_virt;
seL4_IA32_VMAttributes const attr = seL4_IA32_Default_VMAttributes;
@ -152,6 +155,7 @@ class Genode::Vm_space
/**
* Constructor
*
* \param pd_sel selector for page directory
* \param vm_pad_cnode_sel selector for the (2nd-level) VM pad CNode
* \param vm_cnode_sel selector for the (3rd-level) VM CNode
* \param phys_alloc backing store for the CNodes
@ -160,7 +164,8 @@ class Genode::Vm_space
* \param page_table_registry association of VM CNode selectors with
* with virtual addresses
*/
Vm_space(unsigned vm_pad_cnode_sel,
Vm_space(unsigned pd_sel,
unsigned vm_pad_cnode_sel,
unsigned vm_cnode_sel,
Range_allocator &phys_alloc,
Cnode &top_level_cnode,
@ -169,7 +174,8 @@ class Genode::Vm_space
unsigned id,
Page_table_registry &page_table_registry)
:
_page_table_registry(page_table_registry), _id(id),
_page_table_registry(page_table_registry),
_id(id), _pd_sel(pd_sel),
_phys_alloc(phys_alloc),
_top_level_cnode(top_level_cnode),
_phys_cnode(phys_cnode),
@ -188,6 +194,8 @@ class Genode::Vm_space
void map(addr_t from_phys, addr_t to_virt, size_t num_pages)
{
Lock::Guard guard(_lock);
/* check if we need to add a page table to core's VM space */
if (!_page_table_registry.has_page_table_at(to_virt))
_alloc_and_map_page_table(to_virt);
@ -200,6 +208,8 @@ class Genode::Vm_space
void unmap(addr_t virt, size_t num_pages)
{
Lock::Guard guard(_lock);
for (size_t i = 0; i < num_pages; i++) {
off_t const offset = i << get_page_size_log2();
_unmap_page(virt + offset);

View File

@ -0,0 +1,202 @@
/*
* \brief Pager
* \author Norman Feske
* \date 2015-05-01
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/pager.h>
#include <base/sleep.h>
/* core includes */
#include <core_capability_space.h>
#include <install_mapping.h>
/* base-internal includes */
#include <internal/capability_space_sel4.h>
/* seL4 includes */
#include <sel4/interfaces/sel4_client.h>
#include <sel4/arch/pfIPC.h>
using namespace Genode;
static bool const verbose = true;
struct Fault_info
{
addr_t ip = 0;
addr_t pf = 0;
bool write = 0;
Fault_info(seL4_MessageInfo_t msg_info)
:
ip(seL4_GetMR(0)),
pf(seL4_GetMR(1)),
write(seL4_Fault_isWriteFault(seL4_GetMR(3)))
{
if (verbose)
PINF("PF: ip=0x%lx, pf=0x%lx, write=%d", ip, pf, write);
}
};
/***************
** IPC pager **
***************/
void Ipc_pager::wait_for_fault()
{
_last = 0;
reply_and_wait_for_fault();
}
void Ipc_pager::reply_and_wait_for_fault()
{
if (_last)
install_mapping(_reply_mapping, _last);
seL4_Word badge = Rpc_obj_key::INVALID;
seL4_MessageInfo_t page_fault_msg_info;
if (_last) {
seL4_MessageInfo_t const reply_msg = seL4_MessageInfo_new(0, 0, 0, 0);
page_fault_msg_info =
seL4_ReplyWait(Thread_base::myself()->tid().ep_sel, reply_msg, &badge);
} else {
page_fault_msg_info =
seL4_Wait(Thread_base::myself()->tid().ep_sel, &badge);
}
Fault_info const fault_info(page_fault_msg_info);
_pf_ip = fault_info.ip;
_pf_addr = fault_info.pf;
_pf_write = fault_info.write;
_last = badge;
}
void Ipc_pager::acknowledge_wakeup()
{
PDBG("not implemented");
}
Ipc_pager::Ipc_pager()
:
Native_capability(Capability_space::create_ep_cap(*Thread_base::myself())),
_last(0)
{ }
/**********************
** Pager activation **
**********************/
void Pager_activation_base::entry()
{
Ipc_pager pager;
_cap = pager;
_cap_valid.unlock();
bool reply_pending = false;
while (1) {
if (reply_pending)
pager.reply_and_wait_for_fault();
else
pager.wait_for_fault();
reply_pending = false;
/* lookup referenced object */
Object_pool<Pager_object>::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0);
Pager_object *obj = _obj;
/* handle request */
if (obj) {
if (pager.is_exception()) {
obj->submit_exception_signal();
continue;
}
/* send reply if page-fault handling succeeded */
if (!obj->pager(pager))
reply_pending = true;
}
}
}
/******************
** Pager object **
******************/
void Pager_object::wake_up()
{
PDBG("not implemented");
}
void Pager_object::unresolved_page_fault_occurred()
{
state.unresolved_page_fault = true;
}
/**********************
** Pager entrypoint **
**********************/
Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a)
: _activation(a)
{ _activation->ep(this); }
void Pager_entrypoint::dissolve(Pager_object *obj)
{
remove_locked(obj);
}
Pager_capability Pager_entrypoint::manage(Pager_object *obj)
{
/* return invalid capability if no activation is present */
if (!_activation) return Pager_capability();
/*
* Create minted endpoint capability of the pager entrypoint.
* The badge of the page-fault message is used to find the pager
* object for faulted thread.
*/
Native_capability ep_cap = _activation->cap();
Rpc_obj_key rpc_obj_key((addr_t)obj->badge());
Untyped_capability new_obj_cap =
Capability_space::create_rpc_obj_cap(ep_cap, 0, rpc_obj_key);
/* add server object to object pool */
obj->cap(new_obj_cap);
insert(obj);
return reinterpret_cap_cast<Pager_object>(new_obj_cap);
}

View File

@ -348,7 +348,9 @@ Platform::Platform()
_switch_to_core_cspace_done((_switch_to_core_cspace(), true)),
_core_page_table_registry(*core_mem_alloc()),
_init_core_page_table_registry_done((_init_core_page_table_registry(), true)),
_core_vm_space(Core_cspace::CORE_VM_PAD_CNODE_SEL, Core_cspace::CORE_VM_CNODE_SEL,
_core_vm_space(seL4_CapInitThreadPD,
Core_cspace::CORE_VM_PAD_CNODE_SEL,
Core_cspace::CORE_VM_CNODE_SEL,
_phys_alloc,
_top_cnode,
_core_cnode,

View File

@ -18,13 +18,42 @@
#include <platform_pd.h>
#include <platform.h>
#include <util.h>
#include <core_cspace.h>
#include <kernel_object.h>
using namespace Genode;
/*****************************************
** Allocator for protection-domain IDs **
*****************************************/
struct Pd_id_alloc : Bit_allocator<1024>
{
Pd_id_alloc()
{
/*
* Skip 0 because this top-level index is used to address the core
* CNode.
*/
_reserve(0, 1);
_reserve(Core_cspace::CORE_VM_ID, 1);
}
};
static Pd_id_alloc &pd_id_alloc()
{
static Pd_id_alloc inst;
return inst;
}
int Platform_pd::bind_thread(Platform_thread *thread)
{
PDBG("not implemented");
ASSERT(thread);
thread->_pd = this;
return 0;
}
@ -35,14 +64,64 @@ void Platform_pd::unbind_thread(Platform_thread *thread)
}
Untyped_address Platform_pd::_init_page_directory()
{
using namespace Kernel_object;
return create<Page_directory>(*platform()->ram_alloc(),
platform_specific()->core_cnode().sel(),
_page_directory_sel);
}
unsigned Platform_pd::alloc_sel()
{
Lock::Guard guard(_sel_alloc_lock);
return _sel_alloc.alloc();
}
void Platform_pd::free_sel(unsigned sel)
{
Lock::Guard guard(_sel_alloc_lock);
_sel_alloc.free(sel);
}
void Platform_pd::install_mapping(Mapping const &mapping)
{
_vm_space.map(mapping.from_phys(), mapping.to_virt(), mapping.num_pages());
}
Platform_pd::Platform_pd(Allocator * md_alloc, size_t ram_quota,
char const *, signed pd_id, bool create)
{
PDBG("not implemented");
}
:
_id(pd_id_alloc().alloc()),
_page_table_registry(*md_alloc),
_vm_pad_cnode_sel(platform_specific()->alloc_core_sel()),
_vm_cnode_sel(platform_specific()->alloc_core_sel()),
_page_directory_sel(platform_specific()->alloc_core_sel()),
_page_directory(_init_page_directory()),
_vm_space(_page_directory_sel,
_vm_pad_cnode_sel, _vm_cnode_sel,
*platform()->ram_alloc(),
platform_specific()->top_cnode(),
platform_specific()->core_cnode(),
platform_specific()->phys_cnode(),
_id,
_page_table_registry),
_cspace_cnode_sel(platform_specific()->alloc_core_sel()),
_cspace_cnode(platform_specific()->core_cnode().sel(), _cspace_cnode_sel,
CSPACE_SIZE_LOG2,
*platform()->ram_alloc())
{ }
Platform_pd::~Platform_pd()
{
PWRN("not implemented");
platform_specific()->free_core_sel(_vm_cnode_sel);
platform_specific()->free_core_sel(_vm_pad_cnode_sel);
platform_specific()->free_core_sel(_cspace_cnode_sel);
}

View File

@ -17,13 +17,95 @@
/* core includes */
#include <platform_thread.h>
#include <platform_pd.h>
/* base-internal includes */
#include <internal/capability_space_sel4.h>
using namespace Genode;
/*****************************************************
** Implementation of the install_mapping interface **
*****************************************************/
class Platform_thread_registry : Noncopyable
{
private:
List<Platform_thread> _threads;
Lock _lock;
public:
void insert(Platform_thread &thread)
{
Lock::Guard guard(_lock);
_threads.insert(&thread);
}
void remove(Platform_thread &thread)
{
Lock::Guard guard(_lock);
_threads.remove(&thread);
}
void install_mapping(Mapping const &mapping, unsigned long pager_object_badge)
{
Lock::Guard guard(_lock);
for (Platform_thread *t = _threads.first(); t; t = t->next()) {
if (t->pager_object_badge() == pager_object_badge)
t->install_mapping(mapping);
}
}
};
Platform_thread_registry &platform_thread_registry()
{
static Platform_thread_registry inst;
return inst;
}
void Genode::install_mapping(Mapping const &mapping, unsigned long pager_object_badge)
{
platform_thread_registry().install_mapping(mapping, pager_object_badge);
}
/*******************************
** Platform_thread interface **
*******************************/
int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no)
{
PDBG("not implemented");
ASSERT(_pd);
ASSERT(_pager);
/* allocate fault handler selector in the PD's CSpace */
_fault_handler_sel = _pd->alloc_sel();
/* pager endpoint in core */
unsigned const pager_sel = Capability_space::ipc_cap_data(_pager->cap()).sel;
/* install page-fault handler endpoint selector to the PD's CSpace */
_pd->cspace_cnode().copy(platform_specific()->core_cnode(), pager_sel,
_fault_handler_sel);
/* bind thread to PD and CSpace */
seL4_CapData_t const guard_cap_data =
seL4_CapData_Guard_new(0, 32 - _pd->cspace_size_log2());
seL4_CapData_t const no_cap_data = { { 0 } };
int const ret = seL4_TCB_SetSpace(_info.tcb_sel, _fault_handler_sel,
_pd->cspace_cnode().sel(), guard_cap_data,
_pd->page_directory_sel(), no_cap_data);
ASSERT(ret == 0);
start_sel4_thread(_info.tcb_sel, (addr_t)ip, (addr_t)(sp));
return 0;
}
@ -42,14 +124,14 @@ void Platform_thread::resume()
void Platform_thread::state(Thread_state s)
{
PDBG("Not implemented");
PDBG("not implemented");
throw Cpu_session::State_access_failed();
}
Thread_state Platform_thread::state()
{
PDBG("Not implemented");
PDBG("not implemented");
throw Cpu_session::State_access_failed();
}
@ -62,17 +144,35 @@ void Platform_thread::cancel_blocking()
Weak_ptr<Address_space> Platform_thread::address_space()
{
return _address_space;
ASSERT(_pd);
return _pd->weak_ptr();
}
Platform_thread::Platform_thread(size_t, const char *name, unsigned, addr_t)
void Platform_thread::install_mapping(Mapping const &mapping)
{
PDBG("not implemented");
_pd->install_mapping(mapping);
}
Platform_thread::Platform_thread(size_t, const char *name, unsigned priority,
addr_t utcb)
:
_name(name),
_pager_obj_sel(platform_specific()->alloc_core_sel())
{
_info.init(utcb);
platform_thread_registry().insert(*this);
}
Platform_thread::~Platform_thread()
{
PDBG("not implemented");
PDBG("not completely implemented");
platform_thread_registry().remove(*this);
platform_specific()->free_core_sel(_pager_obj_sel);
}

View File

@ -19,77 +19,38 @@
/* core includes */
#include <platform.h>
#include <platform_thread.h>
#include <map_local.h>
#include <kernel_object.h>
#include <thread_sel4.h>
using namespace Genode;
static Untyped_address create_and_map_ipc_buffer(Range_allocator &phys_alloc,
addr_t virt_addr)
{
/* create IPC buffer of one page */
size_t const ipc_buffer_size_log2 = get_page_size_log2();
Untyped_address const untyped_addr =
Untyped_memory::alloc_log2(phys_alloc, ipc_buffer_size_log2);
Untyped_memory::convert_to_page_frames(untyped_addr.phys(), 1);
if (!map_local(untyped_addr.phys(), virt_addr, 1)) {
PERR("could not map IPC buffer phys %lx at local %lx",
untyped_addr.phys(), virt_addr);
}
return untyped_addr;
}
void Thread_base::_init_platform_thread(size_t, Type type)
{
Platform &platform = *platform_specific();
Range_allocator &phys_alloc = *platform.ram_alloc();
addr_t const utcb_virt_addr = (addr_t)&_context->utcb;
Untyped_address const ipc_buffer =
create_and_map_ipc_buffer(phys_alloc, utcb_virt_addr);
/* allocate TCB within core's CNode */
_tid.tcb_sel = platform.alloc_core_sel();
Kernel_object::create<Kernel_object::Tcb>(phys_alloc,
platform.core_cnode().sel(),
_tid.tcb_sel);
/* allocate synchronous endpoint within core's CNode */
_tid.ep_sel = platform.alloc_core_sel();
Kernel_object::create<Kernel_object::Endpoint>(phys_alloc,
platform.core_cnode().sel(),
_tid.ep_sel);
/* assign IPC buffer to thread */
{
/* determine page frame selector of the allocated IPC buffer */
unsigned ipc_buffer_sel = Untyped_memory::frame_sel(ipc_buffer.phys());
int const ret = seL4_TCB_SetIPCBuffer(_tid.tcb_sel, utcb_virt_addr,
ipc_buffer_sel);
if (ret != 0)
PDBG("seL4_TCB_SetIPCBuffer returned %d", ret);
if (type == MAIN) {
_tid.tcb_sel = seL4_CapInitThreadTCB;
return;
}
/* set scheduling priority */
enum { PRIORITY_MAX = 0xff };
seL4_TCB_SetPriority(_tid.tcb_sel, PRIORITY_MAX);
Thread_info thread_info;
thread_info.init(utcb_virt_addr);
/* associate thread with core PD */
{
seL4_CapData_t no_cap_data = { { 0 } };
int const ret = seL4_TCB_SetSpace(_tid.tcb_sel, 0,
platform.top_cnode().sel(), no_cap_data,
seL4_CapInitThreadPD, no_cap_data);
if (ret != 0)
PDBG("seL4_TCB_SetSpace returned %d", ret);
if (!map_local(thread_info.ipc_buffer_phys, utcb_virt_addr, 1)) {
PERR("could not map IPC buffer phys %lx at local %lx",
thread_info.ipc_buffer_phys, utcb_virt_addr);
}
_tid.tcb_sel = thread_info.tcb_sel;
_tid.ep_sel = thread_info.ep_sel;
Platform &platform = *platform_specific();
seL4_CapData_t no_cap_data = { { 0 } };
int const ret = seL4_TCB_SetSpace(_tid.tcb_sel, 0,
platform.top_cnode().sel(), no_cap_data,
seL4_CapInitThreadPD, no_cap_data);
ASSERT(ret == 0);
}
@ -110,21 +71,7 @@ void Thread_base::_thread_start()
void Thread_base::start()
{
/* set register values for the instruction pointer and stack pointer */
seL4_UserContext regs;
Genode::memset(&regs, 0, sizeof(regs));
regs.eip = (uint32_t)&_thread_start;
regs.esp = (uint32_t)stack_top();
regs.gs = IPCBUF_GDT_SELECTOR;
size_t const num_regs = sizeof(regs)/sizeof(seL4_Word);
int const ret = seL4_TCB_WriteRegisters(_tid.tcb_sel, false,
0, num_regs, &regs);
if (ret != 0)
PDBG("seL4_TCB_WriteRegisters returned %d", ret);
seL4_TCB_Resume(_tid.tcb_sel);
start_sel4_thread(_tid.tcb_sel, (addr_t)&_thread_start, (addr_t)stack_top());
}