mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
sel4: bootstrap of init and page-fault handling
This commit is contained in:
parent
691f0eaae7
commit
5a05521e0f
37
repos/base-sel4/include/pd_session/connection.h
Normal file
37
repos/base-sel4/include/pd_session/connection.h
Normal 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_ */
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() { }
|
||||
|
@ -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();
|
||||
}
|
26
repos/base-sel4/src/core/include/install_mapping.h
Normal file
26
repos/base-sel4/src/core/include/install_mapping.h
Normal 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_ */
|
@ -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
|
||||
*
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
/* core includes */
|
||||
#include <util.h>
|
||||
#include <platform_generic.h>
|
||||
#include <platform.h>
|
||||
|
||||
|
||||
namespace Genode {
|
||||
|
@ -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_ */
|
||||
|
@ -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_ */
|
||||
|
110
repos/base-sel4/src/core/include/thread_sel4.h
Normal file
110
repos/base-sel4/src/core/include/thread_sel4.h
Normal 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(®s, 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, ®s);
|
||||
ASSERT(ret == 0);
|
||||
|
||||
seL4_TCB_Resume(tcb_sel);
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__THREAD_SEL4_H_ */
|
@ -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);
|
||||
|
202
repos/base-sel4/src/core/pager.cc
Normal file
202
repos/base-sel4/src/core/pager.cc
Normal 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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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(®s, 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, ®s);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user