mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-04 17:53:07 +00:00
sel4: initialization of non-main threads
This commit is contained in:
parent
06d143d51f
commit
84c5437437
@ -108,17 +108,22 @@ namespace Genode {
|
|||||||
bool valid() const;
|
bool valid() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Native_utcb
|
struct Native_utcb
|
||||||
{
|
{
|
||||||
private:
|
/**
|
||||||
|
* On seL4, the UTCB is called IPC buffer. We use one page
|
||||||
|
* for each IPC buffer.
|
||||||
|
*/
|
||||||
|
enum { IPC_BUFFER_SIZE = 4096 };
|
||||||
|
|
||||||
/**
|
union {
|
||||||
* On seL4, the UTCB is called IPC buffer. We use one page
|
|
||||||
* for each IPC buffer.
|
|
||||||
*/
|
|
||||||
enum { IPC_BUFFER_SIZE = 4096 };
|
|
||||||
|
|
||||||
addr_t _utcb[IPC_BUFFER_SIZE/sizeof(addr_t)];
|
addr_t raw[IPC_BUFFER_SIZE/sizeof(addr_t)];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
addr_t ep_sel;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Native_config
|
struct Native_config
|
||||||
|
@ -215,10 +215,8 @@ class Genode::Capability_space_sel4
|
|||||||
{
|
{
|
||||||
Lock::Guard guard(_lock);
|
Lock::Guard guard(_lock);
|
||||||
|
|
||||||
if (!_is_core_managed(data) && !data.dec_ref()) {
|
if (!_is_core_managed(data) && !data.dec_ref())
|
||||||
PDBG("remove cap");
|
|
||||||
_remove(data);
|
_remove(data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void inc_ref(Data &data)
|
void inc_ref(Data &data)
|
||||||
|
@ -136,7 +136,22 @@ static void decode_seL4_message(umword_t badge,
|
|||||||
|
|
||||||
Rpc_obj_key const rpc_obj_key(seL4_GetMR(MR_IDX_CAPS + i));
|
Rpc_obj_key const rpc_obj_key(seL4_GetMR(MR_IDX_CAPS + i));
|
||||||
|
|
||||||
if (!rpc_obj_key.valid()) {
|
/*
|
||||||
|
* Detect passing of invalid capabilities as arguments
|
||||||
|
*
|
||||||
|
* The second condition of the check handles the case where a non-RPC
|
||||||
|
* object capability as passed as RPC argument as done by the
|
||||||
|
* 'Cap_session::alloc' RPC function. Here, the entrypoint capability
|
||||||
|
* is not an RPC-object capability but a raw seL4 endpoint selector.
|
||||||
|
*
|
||||||
|
* XXX Technically, a message may contain one invalid capability
|
||||||
|
* followed by a valid one. This check would still wrongly regard
|
||||||
|
* the first capability as a valid one. A better approach would
|
||||||
|
* be to introduce another state to Rpc_obj_key, which would
|
||||||
|
* denote a valid capability that is not an RPC-object capability.
|
||||||
|
* Hence it is meaningless as a key.
|
||||||
|
*/
|
||||||
|
if (!rpc_obj_key.valid() && seL4_MessageInfo_get_extraCaps(msg_info) == 0) {
|
||||||
dst_msg.append_cap(Native_capability());
|
dst_msg.append_cap(Native_capability());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -193,8 +208,6 @@ static void decode_seL4_message(umword_t badge,
|
|||||||
|
|
||||||
ASSERT(delegated);
|
ASSERT(delegated);
|
||||||
|
|
||||||
ASSERT(delegated);
|
|
||||||
|
|
||||||
Native_capability arg_cap = Capability_space::lookup(rpc_obj_key);
|
Native_capability arg_cap = Capability_space::lookup(rpc_obj_key);
|
||||||
|
|
||||||
if (arg_cap.valid()) {
|
if (arg_cap.valid()) {
|
||||||
|
@ -29,4 +29,9 @@ void prepare_reinit_main_thread() { prepare_init_main_thread(); }
|
|||||||
** Thread_base **
|
** Thread_base **
|
||||||
*****************/
|
*****************/
|
||||||
|
|
||||||
void Genode::Thread_base::_thread_bootstrap() { }
|
void Genode::Thread_base::_thread_bootstrap()
|
||||||
|
{
|
||||||
|
if (tid().ep_sel == 0) {
|
||||||
|
tid().ep_sel = _context->utcb.ep_sel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,10 +21,4 @@ using namespace Genode;
|
|||||||
|
|
||||||
void Thread_base::_init_platform_thread(size_t, Type type)
|
void Thread_base::_init_platform_thread(size_t, Type type)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* XXX initialize the 'Native_thread' structure with the thread's
|
|
||||||
* tcb_sel, ep_sel.
|
|
||||||
*/
|
|
||||||
|
|
||||||
PDBG("not implemented");
|
|
||||||
}
|
}
|
||||||
|
@ -63,12 +63,8 @@ class Genode::Platform_pd : public Address_space
|
|||||||
Sel_alloc _sel_alloc;
|
Sel_alloc _sel_alloc;
|
||||||
Lock _sel_alloc_lock;
|
Lock _sel_alloc_lock;
|
||||||
|
|
||||||
bool _initial_ipc_buffer_mapped = false;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum { INITIAL_IPC_BUFFER_VIRT = 0x1000 };
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructors
|
* Constructors
|
||||||
*/
|
*/
|
||||||
@ -123,8 +119,6 @@ class Genode::Platform_pd : public Address_space
|
|||||||
size_t cspace_size_log2() { return CSPACE_SIZE_LOG2; }
|
size_t cspace_size_log2() { return CSPACE_SIZE_LOG2; }
|
||||||
|
|
||||||
void install_mapping(Mapping const &mapping);
|
void install_mapping(Mapping const &mapping);
|
||||||
|
|
||||||
void map_ipc_buffer_of_initial_thread(addr_t ipc_buffer_phys);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _CORE__INCLUDE__PLATFORM_PD_H_ */
|
#endif /* _CORE__INCLUDE__PLATFORM_PD_H_ */
|
||||||
|
@ -41,19 +41,32 @@ class Genode::Platform_thread : public List<Platform_thread>::Element
|
|||||||
|
|
||||||
String<128> _name;
|
String<128> _name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual address of the IPC buffer within the PDs address space
|
||||||
|
*
|
||||||
|
* The value is 0 for the PD's main thread. For all other threads,
|
||||||
|
* the value is somewhere within the context area.
|
||||||
|
*/
|
||||||
|
addr_t const _utcb;
|
||||||
|
|
||||||
Thread_info _info;
|
Thread_info _info;
|
||||||
|
|
||||||
unsigned const _pager_obj_sel;
|
unsigned const _pager_obj_sel;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocated when the thread is started
|
* Selectors within the PD's CSpace
|
||||||
|
*
|
||||||
|
* Allocated when the thread is started.
|
||||||
*/
|
*/
|
||||||
unsigned _fault_handler_sel = 0;
|
unsigned _fault_handler_sel = 0;
|
||||||
|
unsigned _ep_sel = 0;
|
||||||
|
|
||||||
friend class Platform_pd;
|
friend class Platform_pd;
|
||||||
|
|
||||||
Platform_pd *_pd = nullptr;
|
Platform_pd *_pd = nullptr;
|
||||||
|
|
||||||
|
enum { INITIAL_IPC_BUFFER_VIRT = 0x1000 };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,6 +36,8 @@ namespace Genode {
|
|||||||
|
|
||||||
addr_t ipc_buffer_phys = 0;
|
addr_t ipc_buffer_phys = 0;
|
||||||
|
|
||||||
|
inline void write_thread_info_to_ipc_buffer(unsigned pd_ep_sel);
|
||||||
|
|
||||||
Thread_info() { }
|
Thread_info() { }
|
||||||
|
|
||||||
inline void init(addr_t const utcb_virt_addr);
|
inline void init(addr_t const utcb_virt_addr);
|
||||||
|
@ -57,6 +57,23 @@ int Platform_pd::bind_thread(Platform_thread *thread)
|
|||||||
ASSERT(thread);
|
ASSERT(thread);
|
||||||
|
|
||||||
thread->_pd = this;
|
thread->_pd = this;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map IPC buffer
|
||||||
|
*
|
||||||
|
* XXX The mapping of the IPC buffer could be evicted from the PD's
|
||||||
|
* 'Vm_space'. In contrast to mapping that are created as a result of
|
||||||
|
* the RM-session's page-fault resolution, the IPC buffer's mapping
|
||||||
|
* won't be recoverable once flushed. For this reason, it is important
|
||||||
|
* to attach the UTCB as a dataspace to the context-area to make the RM
|
||||||
|
* session aware to the mapping. This code is missing.
|
||||||
|
*/
|
||||||
|
if (thread->_utcb) {
|
||||||
|
_vm_space.map(thread->_info.ipc_buffer_phys, thread->_utcb, 1);
|
||||||
|
} else {
|
||||||
|
_vm_space.map(thread->_info.ipc_buffer_phys, thread->INITIAL_IPC_BUFFER_VIRT, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,17 +133,6 @@ void Platform_pd::install_mapping(Mapping const &mapping)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Platform_pd::map_ipc_buffer_of_initial_thread(addr_t ipc_buffer_phys)
|
|
||||||
{
|
|
||||||
if (_initial_ipc_buffer_mapped)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_vm_space.map(ipc_buffer_phys, INITIAL_IPC_BUFFER_VIRT, 1);
|
|
||||||
|
|
||||||
_initial_ipc_buffer_mapped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Platform_pd::Platform_pd(Allocator * md_alloc, size_t ram_quota,
|
Platform_pd::Platform_pd(Allocator * md_alloc, size_t ram_quota,
|
||||||
char const *, signed pd_id, bool create)
|
char const *, signed pd_id, bool create)
|
||||||
:
|
:
|
||||||
|
@ -75,6 +75,38 @@ void Genode::install_mapping(Mapping const &mapping, unsigned long pager_object_
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************
|
||||||
|
** Utilities to support the Platform_thread interface **
|
||||||
|
********************************************************/
|
||||||
|
|
||||||
|
static void prepopulate_ipc_buffer(addr_t ipc_buffer_phys, unsigned ep_sel)
|
||||||
|
{
|
||||||
|
/* IPC buffer is one page */
|
||||||
|
size_t const page_rounded_size = get_page_size();
|
||||||
|
|
||||||
|
/* allocate range in core's virtual address space */
|
||||||
|
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 IPC buffer to core-local virtual addresses */
|
||||||
|
map_local(ipc_buffer_phys, (addr_t)virt_addr, 1);
|
||||||
|
|
||||||
|
/* populate IPC buffer with thread information */
|
||||||
|
Native_utcb &utcb = *(Native_utcb *)virt_addr;
|
||||||
|
utcb.ep_sel = ep_sel;
|
||||||
|
|
||||||
|
/* unmap IPC buffer from core */
|
||||||
|
unmap_local((addr_t)virt_addr, 1);
|
||||||
|
|
||||||
|
/* free core's virtual address space */
|
||||||
|
platform()->region_alloc()->free(virt_addr, page_rounded_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************
|
/*******************************
|
||||||
** Platform_thread interface **
|
** Platform_thread interface **
|
||||||
*******************************/
|
*******************************/
|
||||||
@ -94,7 +126,19 @@ int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no)
|
|||||||
_pd->cspace_cnode().copy(platform_specific()->core_cnode(), pager_sel,
|
_pd->cspace_cnode().copy(platform_specific()->core_cnode(), pager_sel,
|
||||||
_fault_handler_sel);
|
_fault_handler_sel);
|
||||||
|
|
||||||
_pd->map_ipc_buffer_of_initial_thread(_info.ipc_buffer_phys);
|
/* allocate endpoint selector in the PD's CSpace */
|
||||||
|
_ep_sel = _pd->alloc_sel();
|
||||||
|
|
||||||
|
/* install the thread's endpoint selector to the PD's CSpace */
|
||||||
|
_pd->cspace_cnode().copy(platform_specific()->core_cnode(), _info.ep_sel,
|
||||||
|
_ep_sel);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Populate the thread's IPC buffer with initial information about the
|
||||||
|
* thread. Once started, the thread picks up this information in the
|
||||||
|
* 'Thread_base::_thread_bootstrap' method.
|
||||||
|
*/
|
||||||
|
prepopulate_ipc_buffer(_info.ipc_buffer_phys, _ep_sel);
|
||||||
|
|
||||||
/* bind thread to PD and CSpace */
|
/* bind thread to PD and CSpace */
|
||||||
seL4_CapData_t const guard_cap_data =
|
seL4_CapData_t const guard_cap_data =
|
||||||
@ -161,10 +205,11 @@ Platform_thread::Platform_thread(size_t, const char *name, unsigned priority,
|
|||||||
addr_t utcb)
|
addr_t utcb)
|
||||||
:
|
:
|
||||||
_name(name),
|
_name(name),
|
||||||
|
_utcb(utcb),
|
||||||
_pager_obj_sel(platform_specific()->alloc_core_sel())
|
_pager_obj_sel(platform_specific()->alloc_core_sel())
|
||||||
|
|
||||||
{
|
{
|
||||||
_info.init(Platform_pd::INITIAL_IPC_BUFFER_VIRT);
|
_info.init(_utcb ? _utcb : INITIAL_IPC_BUFFER_VIRT);
|
||||||
platform_thread_registry().insert(*this);
|
platform_thread_registry().insert(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user