From 7550f243ad3096a6b0784a9dc1cf2b073fcacbce Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 8 Aug 2012 14:23:13 +0200 Subject: [PATCH] NOVA: use cap_session to allocate portals --- base-nova/include/base/pager.h | 17 ++- base-nova/include/nova/util.h | 44 +++++++ base-nova/src/base/pager/pager.cc | 81 ++++++------- base-nova/src/base/server/server.cc | 148 ++++++++++------------- base-nova/src/base/thread/thread_nova.cc | 100 +++++++-------- base-nova/src/core/thread_start.cc | 15 ++- 6 files changed, 224 insertions(+), 181 deletions(-) create mode 100644 base-nova/include/nova/util.h diff --git a/base-nova/include/base/pager.h b/base-nova/include/base/pager.h index aafc396caa..126aa6a8de 100644 --- a/base-nova/include/base/pager.h +++ b/base-nova/include/base/pager.h @@ -75,7 +75,12 @@ namespace Genode { /** * Return base of initial portal window */ - unsigned exc_pt_sel() { return _tid.exc_pt_sel; } + addr_t ec_sel() { return _tid.ec_sel; } + + /** + * Return base of initial portal window + */ + addr_t exc_pt_sel() { return _tid.exc_pt_sel; } /** * Set initial stack pointer used by the startup handler @@ -107,6 +112,16 @@ namespace Genode { Signal_transmitter transmitter(_exception_sigh); transmitter.submit(); } + + + /** + * Return entry point address + */ + addr_t handler_address() + { + return reinterpret_cast(_invoke_handler); + } + }; diff --git a/base-nova/include/nova/util.h b/base-nova/include/nova/util.h new file mode 100644 index 0000000000..f19662be53 --- /dev/null +++ b/base-nova/include/nova/util.h @@ -0,0 +1,44 @@ +/* + * \brief Helper code used by core as base framework + * \author Alexander Boettcher + * \date 2012-08-08 + */ + +/* + * Copyright (C) 2012-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 _NOVA__INCLUDE__UTIL_H_ +#define _NOVA__INCLUDE__UTIL_H_ + +#include +#include + +inline void request_event_portal(Genode::Native_capability cap, + Genode::addr_t exc_base, Genode::addr_t event) +{ + using namespace Nova; + Utcb *utcb = (Utcb *)Genode::Thread_base::myself()->utcb(); + + /* save original receive window */ + Crd orig_crd = utcb->crd_rcv; + + /* request event-handler portal */ + utcb->crd_rcv = Obj_crd(exc_base + event, 0); + utcb->msg[0] = event; + utcb->set_msg_word(1); + + uint8_t res = call(pager_cap.dst()); + if (res) + PERR("request of event (%lu) capability selector failed", + event); + + /* restore original receive window */ + utcb->crd_rcv = orig_crd; +} + + +#endif /* _NOVA__INCLUDE__UTIL_H_ */ diff --git a/base-nova/src/base/pager/pager.cc b/base-nova/src/base/pager/pager.cc index 82a6f9b366..47634f7f76 100644 --- a/base-nova/src/base/pager/pager.cc +++ b/base-nova/src/base/pager/pager.cc @@ -33,7 +33,8 @@ void Pager_object::_page_fault_handler() /* serialize page-fault handling */ Thread_base *myself = Thread_base::myself(); if (!myself) { - PWRN("unexpected page-fault for non-existing pager object, going to sleep forever"); + PWRN("unexpected page-fault for non-existing pager object," + " going to sleep forever"); sleep_forever(); } @@ -41,10 +42,12 @@ void Pager_object::_page_fault_handler() int ret = obj->pager(ipc_pager); if (ret) { - PWRN("page-fault resolution for address 0x%lx, ip=0x%lx failed", + PWRN("unresolvable page-fault at address 0x%lx, ip=0x%lx", ipc_pager.fault_addr(), ipc_pager.fault_ip()); - /* revoke paging capability */ - Nova::revoke(Nova::Obj_crd(obj->exc_pt_sel() + PT_SEL_PAGE_FAULT, 0), true); + + /* revoke paging capability, let thread die in kernel */ + Nova::revoke(Obj_crd(obj->exc_pt_sel() + PT_SEL_PAGE_FAULT, 0), + true); Utcb *utcb = (Utcb *)Thread_base::myself()->utcb(); utcb->set_msg_word(0); } @@ -58,8 +61,8 @@ void Pager_object::_startup_handler() Pager_object *obj = static_cast(Thread_base::myself()); Utcb *utcb = (Utcb *)Thread_base::myself()->utcb(); - printf("start new pager object with EIP=0x%p, ESP=0x%p\n", - (void *)obj->_initial_eip, (void *)obj->_initial_esp); +// printf("start new pager object with EIP=0x%p, ESP=0x%p\n", +// (void *)obj->_initial_eip, (void *)obj->_initial_esp); utcb->eip = obj->_initial_eip; utcb->esp = obj->_initial_esp; @@ -80,7 +83,8 @@ void Pager_object::_invoke_handler() utcb->set_msg_word(0); if (event == PT_SEL_STARTUP || event == PT_SEL_PAGE_FAULT) { - bool res = utcb->append_item(Obj_crd(obj->exc_pt_sel() + event, 0), 0); + bool res = utcb->append_item(Obj_crd(obj->exc_pt_sel() + event, + 0), 0); /* one item ever fits on the UTCB */ (void)res; } @@ -99,22 +103,12 @@ Pager_object::Pager_object(unsigned long badge) enum { CPU_NO = 0, GLOBAL = false, EXC_BASE = 0 }; - mword_t *thread_sp = (mword_t *)&_context->stack[-4]; - mword_t thread_utcb = (mword_t) &_context->utcb; - - /* create local EC */ - uint8_t res = create_ec(_tid.ec_sel, pd_sel, - CPU_NO, thread_utcb, - (mword_t)thread_sp, /* <- delivered to the startup handler */ - EXC_BASE, GLOBAL); - if (res) - PERR("create_ec returned %d - utcb 0x%lx", res, thread_utcb); - /* create portal for page-fault handler */ - res = create_pt(exc_pt_sel() + PT_SEL_PAGE_FAULT, pd_sel, _tid.ec_sel, - Mtd(Mtd::QUAL | Mtd::EIP), (mword_t)_page_fault_handler); + uint8_t res = create_pt(exc_pt_sel() + PT_SEL_PAGE_FAULT, pd_sel, + _tid.ec_sel, Mtd(Mtd::QUAL | Mtd::EIP), + (mword_t)_page_fault_handler); if (res) { - PERR("could not create page-fault portal, create_pt returned %d\n", + PERR("could not create page-fault portal, error = %u\n", res); class Create_page_fault_pt_failed { }; throw Create_page_fault_pt_failed(); @@ -124,7 +118,7 @@ Pager_object::Pager_object(unsigned long badge) res = create_pt(exc_pt_sel() + PT_SEL_STARTUP, pd_sel, _tid.ec_sel, Mtd(Mtd::ESP | Mtd::EIP), (mword_t)_startup_handler); if (res) { - PERR("could not create startup portal, create_pt returned %d\n", + PERR("could not create startup portal, error = %u\n", res); class Create_startup_pt_failed { }; throw Create_startup_pt_failed(); @@ -132,19 +126,23 @@ Pager_object::Pager_object(unsigned long badge) /* * Create object identity representing the pager object. It is used as - * argument to 'Cpu_session::set_pager'. Furthermore it can be invoked to - * request the mapping of the event capability selector window + * argument to 'Cpu_session::set_pager'. Furthermore it can be invoked + * to request the mapping of the event capability selector window * corresponding to the pager object. */ _pt_sel = cap_selector_allocator()->alloc(); - res = create_pt(_pt_sel, pd_sel, _tid.ec_sel, Mtd(0), (mword_t)_invoke_handler); + res = create_pt(_pt_sel, pd_sel, _tid.ec_sel, Mtd(0), + reinterpret_cast(_invoke_handler)); if (res) - PERR("could not create pager object identity, create_pt returned %d\n", res); + PERR("could not create pager object identity, error = %u\n", + res); _pt_cleanup = cap_selector_allocator()->alloc(); - res = create_pt(_pt_cleanup, pd_sel, _tid.ec_sel, Mtd(0), (mword_t)_invoke_handler); + res = create_pt(_pt_cleanup, pd_sel, _tid.ec_sel, Mtd(0), + reinterpret_cast(_invoke_handler)); if (res) - PERR("could not create pager cleanup portal, create_pt returned %d\n", res); + PERR("could not create pager cleanup portal, error = %u\n", + res); } Pager_object::~Pager_object() @@ -178,33 +176,32 @@ Pager_object::~Pager_object() Pager_capability Pager_entrypoint::manage(Pager_object *obj) { - /* supplement capability with object ID obtained from CAP session */ - Native_capability cap_session = _cap_session->alloc(Native_capability(obj->pt_sel(), 0)); + /* request creation of portal bind to pager thread */ + Native_capability pager_thread_cap(obj->ec_sel(), 0); + Native_capability cap_session = _cap_session->alloc(pager_thread_cap, + obj->handler_address()); - /* - * cap_session.local_name() contains now the global object id. - * We drop it here since there is no need on NOVA to have it, - * instead we use solely the dst id and the local obj id. - */ - cap_session = Native_capability(cap_session.dst(), obj->pt_sel()); + cap_session = Native_capability(cap_session.dst(), cap_session.dst()); /* add server object to object pool */ obj->Object_pool::Entry::cap(cap_session); insert(obj); /* return capability that uses the object id as badge */ - return reinterpret_cap_cast(obj->Object_pool::Entry::cap()); + return reinterpret_cap_cast( + obj->Object_pool::Entry::cap()); } void Pager_entrypoint::dissolve(Pager_object *obj) { - /* cleanup cap session */ + /* cleanup at cap session */ _cap_session->free(obj->Object_pool::Entry::cap()); - if (obj->pt_sel() != 0UL + obj->Object_pool::Entry::cap().dst()) { - cap_selector_allocator()->free(obj->Object_pool::Entry::cap().dst(), 0); - revoke(Obj_crd(obj->Object_pool::Entry::cap().dst(), 0), true); - } + + /* cleanup locally */ + addr_t pager_pt = obj->Object_pool::Entry::cap().dst(); + revoke(Obj_crd(pager_pt, 0), true); + cap_selector_allocator()->free(pager_pt, 0); remove(obj); } diff --git a/base-nova/src/base/server/server.cc b/base-nova/src/base/server/server.cc index 14e1bc40ec..012106563a 100644 --- a/base-nova/src/base/server/server.cc +++ b/base-nova/src/base/server/server.cc @@ -15,24 +15,17 @@ /* Genode includes */ #include #include +#include #include /* NOVA includes */ #include +#include +#include using namespace Genode; -/** - * Function gets called during destruction of an entrypoint. - * It is just here to make sure nobody else is in the entrypoint - * anymore (all communication portals must be revoked beforehand). - */ -static void _cleanup_entry() -{ - Nova::reply(Thread_base::myself()->stack_top()); -} - /*********************** ** Server entrypoint ** ***********************/ @@ -41,39 +34,16 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj) { using namespace Nova; - unsigned ec_sel = tid().ec_sel; - addr_t pt_sel = cap_selector_allocator()->alloc(1); - unsigned pd_sel = cap_selector_allocator()->pd_sel(); + Untyped_capability ep_cap, new_obj_cap; - /* create portal */ - uint8_t res = create_pt(pt_sel, pd_sel, ec_sel, Mtd(0), - (mword_t)_activation_entry); - if (res) { - PERR("could not create server-object portal, create_pt returned %d\n", - res); - return Untyped_capability(); - } - /* create cleanup portal */ - res = create_pt(pt_sel + 1, pd_sel, ec_sel, Mtd(0), - (mword_t)_cleanup_entry); - if (res) { - PERR("could not create server-object-cleanup portal, create_pt returned %d\n", - res); - return Untyped_capability(); - } + /* _ec_sel is invalid until thread gets started */ + if (tid().ec_sel != ~0UL) + ep_cap = Native_capability(tid().ec_sel, 0); + else + ep_cap = Native_capability(_thread_cap.dst(), 0); - /* create capability to portal as destination address */ - Untyped_capability ep_cap = Native_capability(pt_sel, 0); - - /* supplement capability with object ID obtained from CAP session */ - Untyped_capability new_obj_cap = _cap_session->alloc(ep_cap); - - /* - * new_obj_cap.local_name() contains now the global object id. - * We drop it here since there is no need on NOVA to have it, - * instead we use solely the dst id and the local obj id. - */ - new_obj_cap = Native_capability(new_obj_cap.dst(), pt_sel); + new_obj_cap = _cap_session->alloc(ep_cap, (addr_t)_activation_entry); + new_obj_cap = Native_capability(new_obj_cap.dst(), new_obj_cap.dst()); /* add server object to object pool */ obj->cap(new_obj_cap); @@ -86,11 +56,8 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj) void Rpc_entrypoint::_dissolve(Rpc_object_base *obj) { - /* Avoid any incoming IPC early */ - Nova::revoke(Nova::Obj_crd(obj->cap().local_name(), 0), true); - /* If the dst is not the same, revoke the cap locally */ - if (obj->cap().dst() != obj->cap().local_name()) - Nova::revoke(Nova::Obj_crd(obj->cap().dst(), 0), true); + /* Avoid any incoming IPC early, keep local selector */ + Nova::revoke(Nova::Obj_crd(obj->cap().local_name(), 0), false); /* make sure nobody is able to find this object */ remove(obj); @@ -109,16 +76,13 @@ void Rpc_entrypoint::_dissolve(Rpc_object_base *obj) /* wait until nobody is inside dispatch */ obj->lock(); - /* now the object may be safely destructed */ - + /* De-announce object from cap_session */ _cap_session->free(obj->cap()); - /* revoke cleanup portal */ - Nova::revoke(Nova::Obj_crd(obj->cap().local_name() + 1, 0), true); - /* free 2 cap selectors */ - cap_selector_allocator()->free(obj->cap().local_name(), 1); - /* free dst cap selector if it wasn't the same as the local_name */ - if (obj->cap().dst() != obj->cap().local_name()) - cap_selector_allocator()->free(obj->cap().dst(), 0); + + /* Revoke local selector finally */ + Nova::revoke(Nova::Obj_crd(obj->cap().local_name(), 0), true); + /* free cap selector ??? XXX */ + //cap_selector_allocator()->free(obj->cap().local_name(), 0); } @@ -150,10 +114,16 @@ void Rpc_entrypoint::_activation_entry() Lock::Guard lock_guard(ep->_curr_obj_lock); ep->_curr_obj = ep->obj_by_id(id_pt); - if (!ep->_curr_obj) { - PERR("could not look up server object, return from call badge=%lx id_pt=%lx", srv.badge(), id_pt); - ep->_curr_obj_lock.unlock(); - srv << IPC_REPLY; + if (!ep->_curr_obj || !id_pt) { + ep->_curr_obj = ep->obj_by_id(srv.badge()); + if (!ep->_curr_obj) { + PERR("could not look up server object, " + " return from call badge=%lx id_pt=%lx", + srv.badge(), id_pt); + + ep->_curr_obj_lock.unlock(); + srv << IPC_REPLY; + } } ep->_curr_obj->lock(); @@ -188,12 +158,13 @@ void Rpc_entrypoint::_leave_server_object(Rpc_object_base *obj) cancel_blocking(); } - Nova::Utcb *utcb = reinterpret_cast(Thread_base::myself()->utcb()); + Nova::Utcb *utcb = reinterpret_cast( + Thread_base::myself()->utcb()); /* don't call ourself */ if (utcb != reinterpret_cast(&_context->utcb)) { utcb->set_msg_word(0); - if (Nova::call(obj->cap().local_name() + 1)) - PERR("could not clean up entry point"); + if (uint8_t res = Nova::call(obj->cap().local_name())) + PERR("could not clean up entry point - %u", res); } } @@ -205,10 +176,11 @@ void Rpc_entrypoint::activate() { /* * In contrast to a normal thread, a server activation is created at - * construction time. However, it executes no code because processing time - * is always provided by the caller of the server activation. To delay the - * processing of requests until the 'activate' function is called, we grab the - * '_curr_obj_lock' on construction and release it here. + * construction time. However, it executes no code because processing + * time is always provided by the caller of the server activation. To + * delay the processing of requests until the 'activate' function is + * called, we grab the '_curr_obj_lock' on construction and release it + * here. */ _curr_obj_lock.unlock(); } @@ -222,25 +194,39 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, _curr_obj_lock(Lock::LOCKED), _cap_session(cap_session) { - using namespace Nova; - - /* - * Create EC here to ensure that 'tid()' returns a valid 'ec_sel' - * portal selector even before 'activate' is called. + /** + * Create thread if we aren't running in core. + * + * For core this code can't be performed since the sessions aren't + * setup in the early bootstrap phase of core. In core the thread + * is created 'manually'. */ + if (_tid.ec_sel == ~0UL) { + /* create new pager object and assign it to the new thread */ + Pager_capability pager_cap = + env()->rm_session()->add_client(_thread_cap); + env()->cpu_session()->set_pager(_thread_cap, pager_cap); - mword_t *sp = (mword_t *)&_context->stack[-4]; - mword_t utcb = (mword_t) &_context->utcb; + addr_t thread_sp = (addr_t)&_context->stack[-4]; + Genode::Nova_cpu_connection cpu; + cpu.start_exc_base_vcpu(_thread_cap, 0, thread_sp, + _tid.exc_pt_sel); - /* create local EC */ - enum { CPU_NO = 0, GLOBAL = false }; - int res = create_ec(_tid.ec_sel, Cap_selector_allocator::pd_sel(), - CPU_NO, utcb, (mword_t)sp, - _tid.exc_pt_sel, GLOBAL); - if (res) - PDBG("create_ec returned %d", res); + request_event_portal(pager_cap, _tid.exc_pt_sel, + Nova::PT_SEL_STARTUP); + request_event_portal(pager_cap, _tid.exc_pt_sel, + Nova::PT_SEL_PAGE_FAULT); - _rcv_buf.rcv_prepare_pt_sel_window((Utcb *)utcb); + /** + * Request native thread cap, _thread_cap only a token. + * The native thread cap is required to attach new rpc objects + * (to create portals bound to the ec) + */ + Native_capability ec_cap = cpu.native_cap(_thread_cap); + _tid.ec_sel = ec_cap.dst(); + } + + _rcv_buf.rcv_prepare_pt_sel_window((Nova::Utcb *)&_context->utcb); if (start_on_construction) activate(); diff --git a/base-nova/src/base/thread/thread_nova.cc b/base-nova/src/base/thread/thread_nova.cc index 77a4055a90..f88692f3e6 100644 --- a/base-nova/src/base/thread/thread_nova.cc +++ b/base-nova/src/base/thread/thread_nova.cc @@ -19,8 +19,13 @@ #include #include +#include +#include + /* NOVA includes */ #include +#include +#include using namespace Genode; @@ -35,29 +40,6 @@ void Thread_base::_thread_start() } -static void request_event_portal(Pager_capability pager_cap, - int exc_base, int event) -{ - using namespace Nova; - Utcb *utcb = (Utcb *)Thread_base::myself()->utcb(); - - /* save original receive window */ - Crd orig_crd = utcb->crd_rcv; - - /* request event-handler portal */ - utcb->msg[0] = event; - utcb->set_msg_word(1); - utcb->crd_rcv = Obj_crd(exc_base + event, 0); - - int res = call(pager_cap.dst()); - if (res) - PERR("request of event (%d) capability selector failed", event); - - /* restore original receive window */ - utcb->crd_rcv = orig_crd; -} - - /***************** ** Thread base ** *****************/ @@ -68,10 +50,9 @@ void Thread_base::_init_platform_thread() /* * Allocate capability selectors for the thread's execution context, - * scheduling context, running semaphore and exception handler portals. + * running semaphore and exception handler portals. */ - _tid.ec_sel = cap_selector_allocator()->alloc(); - _tid.sc_sel = cap_selector_allocator()->alloc(); + _tid.ec_sel = ~0UL; _tid.rs_sel = cap_selector_allocator()->alloc(); _tid.pd_sel = cap_selector_allocator()->pd_sel(); _tid.exc_pt_sel = cap_selector_allocator()->alloc(NUM_INITIAL_PT_LOG2); @@ -81,33 +62,30 @@ void Thread_base::_init_platform_thread() name(buf, sizeof(buf)); _thread_cap = env()->cpu_session()->create_thread(buf); + /* assign thread to protection domain */ + env()->pd_session()->bind_thread(_thread_cap); + /* create new pager object and assign it to the new thread */ Pager_capability pager_cap = env()->rm_session()->add_client(_thread_cap); env()->cpu_session()->set_pager(_thread_cap, pager_cap); - /* register initial IP and SP at core */ - mword_t thread_sp = (mword_t)&_context->stack[-4]; - env()->cpu_session()->start(_thread_cap, (addr_t)_thread_start, thread_sp); - - request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_STARTUP); - request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_PAGE_FAULT); - /* create running semaphore required for locking */ - int res = create_sm(_tid.rs_sel, _tid.pd_sel, 0); - if (res) - PERR("create_sm returned %d", res); + uint8_t res = create_sm(_tid.rs_sel, _tid.pd_sel, 0); + if (res != NOVA_OK) { + PERR("create_sm returned %u", res); + throw Cpu_session::Thread_creation_failed(); + } + } void Thread_base::_deinit_platform_thread() { - Nova::revoke(Nova::Obj_crd(_tid.sc_sel, 0)); - Nova::revoke(Nova::Obj_crd(_tid.ec_sel, 0)); +// Nova::revoke(Nova::Obj_crd(_tid.ec_sel, 0)); Nova::revoke(Nova::Obj_crd(_tid.rs_sel, 0)); Nova::revoke(Nova::Obj_crd(_tid.exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2)); - cap_selector_allocator()->free(_tid.ec_sel, 0); - cap_selector_allocator()->free(_tid.sc_sel, 0); +// cap_selector_allocator()->free(_tid.ec_sel, 0); cap_selector_allocator()->free(_tid.rs_sel, 0); cap_selector_allocator()->free(_tid.exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2); @@ -123,25 +101,35 @@ void Thread_base::_deinit_platform_thread() void Thread_base::start() { + if (_tid.ec_sel != ~0UL) + throw Cpu_session::Thread_creation_failed(); + + using namespace Genode; + + /* create new pager object and assign it to the new thread */ + Pager_capability pager_cap = env()->rm_session()->add_client(_thread_cap); + env()->cpu_session()->set_pager(_thread_cap, pager_cap); + + /* create EC at core */ + addr_t thread_sp = reinterpret_cast(&_context->stack[-4]); + + Genode::Nova_cpu_connection cpu; + if (cpu.start_exc_base_vcpu(_thread_cap, (addr_t)_thread_start, + thread_sp, _tid.exc_pt_sel)) + throw Cpu_session::Thread_creation_failed(); + + /* request native EC thread cap */ + Native_capability ec_cap = cpu.native_cap(_thread_cap); + _tid.ec_sel = ec_cap.dst(); + using namespace Nova; - /* create execution context */ - enum { THREAD_CPU_NO = 0, THREAD_GLOBAL = true }; - int res = create_ec(_tid.ec_sel, _tid.pd_sel, THREAD_CPU_NO, (mword_t)&_context->utcb, - 0, _tid.exc_pt_sel, THREAD_GLOBAL); - if (res) - PDBG("create_ec returned %d", res); + /* request exception portals */ + request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_STARTUP); + request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_PAGE_FAULT); - /* - * Create scheduling context - * - * With assigning a scheduling context to the execution context, the new - * thread will immediately start, enter the startup portal, and receives - * the configured initial IP and SP from core. - */ - res = create_sc(_tid.sc_sel, _tid.pd_sel, _tid.ec_sel, Qpd()); - if (res) - PERR("create_sc returned %d", res); + /* request creation of SC to let thread run*/ + env()->cpu_session()->resume(_thread_cap); } diff --git a/base-nova/src/core/thread_start.cc b/base-nova/src/core/thread_start.cc index 956aaf956b..7c54a54111 100644 --- a/base-nova/src/core/thread_start.cc +++ b/base-nova/src/core/thread_start.cc @@ -36,7 +36,6 @@ using namespace Genode; void Thread_base::_init_platform_thread() { _tid.ec_sel = cap_selector_allocator()->alloc(); - _tid.sc_sel = ~0; /* not needed within core */ _tid.rs_sel = cap_selector_allocator()->alloc(); _tid.pd_sel = cap_selector_allocator()->pd_sel(); _tid.exc_pt_sel = cap_selector_allocator()->alloc(Nova::NUM_INITIAL_PT_LOG2); @@ -45,6 +44,20 @@ void Thread_base::_init_platform_thread() uint8_t res = Nova::create_sm(_tid.rs_sel, _tid.pd_sel, 0); if (res) PERR("create_sm returned %u", res); + + addr_t sp = reinterpret_cast(&_context->stack[-4]); + addr_t utcb = reinterpret_cast(&_context->utcb); + + /* create local EC */ + enum { CPU_NO = 0, GLOBAL = false }; + res = Nova::create_ec(_tid.ec_sel, Cap_selector_allocator::pd_sel(), + CPU_NO, utcb, sp, + _tid.exc_pt_sel, GLOBAL); + if (res) { + PERR("%p - create_ec returned %d", this, res); + PERR("valid thread %x %lx:%lx", _thread_cap.valid(), + _thread_cap.dst(), _thread_cap.local_name()); + } }