mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +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;
|
||||
};
|
||||
|
||||
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 };
|
||||
|
||||
/**
|
||||
* On seL4, the UTCB is called IPC buffer. We use one page
|
||||
* for each IPC buffer.
|
||||
*/
|
||||
enum { IPC_BUFFER_SIZE = 4096 };
|
||||
union {
|
||||
|
||||
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
|
||||
|
@ -215,10 +215,8 @@ class Genode::Capability_space_sel4
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_is_core_managed(data) && !data.dec_ref()) {
|
||||
PDBG("remove cap");
|
||||
if (!_is_core_managed(data) && !data.dec_ref())
|
||||
_remove(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));
|
||||
|
||||
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());
|
||||
continue;
|
||||
}
|
||||
@ -193,8 +208,6 @@ static void decode_seL4_message(umword_t badge,
|
||||
|
||||
ASSERT(delegated);
|
||||
|
||||
ASSERT(delegated);
|
||||
|
||||
Native_capability arg_cap = Capability_space::lookup(rpc_obj_key);
|
||||
|
||||
if (arg_cap.valid()) {
|
||||
|
@ -29,4 +29,9 @@ void prepare_reinit_main_thread() { prepare_init_main_thread(); }
|
||||
** 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)
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
Lock _sel_alloc_lock;
|
||||
|
||||
bool _initial_ipc_buffer_mapped = false;
|
||||
|
||||
public:
|
||||
|
||||
enum { INITIAL_IPC_BUFFER_VIRT = 0x1000 };
|
||||
|
||||
/**
|
||||
* Constructors
|
||||
*/
|
||||
@ -123,8 +119,6 @@ class Genode::Platform_pd : public Address_space
|
||||
size_t cspace_size_log2() { return CSPACE_SIZE_LOG2; }
|
||||
|
||||
void install_mapping(Mapping const &mapping);
|
||||
|
||||
void map_ipc_buffer_of_initial_thread(addr_t ipc_buffer_phys);
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__PLATFORM_PD_H_ */
|
||||
|
@ -41,19 +41,32 @@ class Genode::Platform_thread : public List<Platform_thread>::Element
|
||||
|
||||
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;
|
||||
|
||||
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 _ep_sel = 0;
|
||||
|
||||
friend class Platform_pd;
|
||||
|
||||
Platform_pd *_pd = nullptr;
|
||||
|
||||
enum { INITIAL_IPC_BUFFER_VIRT = 0x1000 };
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
|
@ -36,6 +36,8 @@ namespace Genode {
|
||||
|
||||
addr_t ipc_buffer_phys = 0;
|
||||
|
||||
inline void write_thread_info_to_ipc_buffer(unsigned pd_ep_sel);
|
||||
|
||||
Thread_info() { }
|
||||
|
||||
inline void init(addr_t const utcb_virt_addr);
|
||||
|
@ -57,6 +57,23 @@ int Platform_pd::bind_thread(Platform_thread *thread)
|
||||
ASSERT(thread);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
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 **
|
||||
*******************************/
|
||||
@ -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,
|
||||
_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 */
|
||||
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)
|
||||
:
|
||||
_name(name),
|
||||
_utcb(utcb),
|
||||
_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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user