diff --git a/base-nova/include/nova/util.h b/base-nova/include/nova/util.h index 889b18032..ba22ef8f8 100644 --- a/base-nova/include/nova/util.h +++ b/base-nova/include/nova/util.h @@ -29,8 +29,8 @@ inline void nova_die(const char * text = 0) } -inline void request_event_portal(Genode::Native_capability cap, - Genode::addr_t exc_base, Genode::addr_t event, +inline void request_event_portal(Genode::Native_capability const &cap, + Genode::addr_t sel, Genode::addr_t event, unsigned short log2_count = 0) { using namespace Nova; @@ -40,7 +40,7 @@ inline void request_event_portal(Genode::Native_capability cap, Crd orig_crd = utcb->crd_rcv; /* request event-handler portal */ - utcb->crd_rcv = Obj_crd(exc_base + event, log2_count); + utcb->crd_rcv = Obj_crd(sel, log2_count); utcb->msg[0] = event; utcb->msg[1] = log2_count; utcb->set_msg_word(2); @@ -53,4 +53,9 @@ inline void request_event_portal(Genode::Native_capability cap, utcb->crd_rcv = orig_crd; } + +inline void request_native_ec_cap(Genode::Native_capability const &cap, + Genode::addr_t sel) { + request_event_portal(cap, sel , ~0U, 0); } + #endif /* _NOVA__INCLUDE__UTIL_H_ */ diff --git a/base-nova/src/base/pager/pager.cc b/base-nova/src/base/pager/pager.cc index 659fbb042..d45ab7073 100644 --- a/base-nova/src/base/pager/pager.cc +++ b/base-nova/src/base/pager/pager.cc @@ -192,18 +192,37 @@ void Pager_object::_invoke_handler() /* send single portal as reply */ addr_t const event = utcb->msg[0]; addr_t const logcount = utcb->msg[1]; + utcb->mtd = 0; utcb->set_msg_word(0); + if (event == ~0UL) { + /** + * Return native EC cap with specific rights mask set. + * If the cap is mapped the kernel will demote the + * rights of the EC as specified by the rights mask. + * + * The cap is supposed to be returned to clients, + * which they have to use as argument to identify + * the thread to which they want attach portals. + * + * The demotion by the kernel during the map operation + * takes care that the EC cap itself contains + * no usable rights for the clients. + */ + bool res = utcb->append_item(Obj_crd(obj->_state.sel_client_ec, 0, + Obj_crd::RIGHT_EC_RECALL), 0); + (void)res; + reply(myself->stack_top()); + } + + /* sanity check - if event is not valid return nothing */ if (logcount > NUM_INITIAL_PT_LOG2 || event > 1UL << NUM_INITIAL_PT_LOG2 || event + (1UL << logcount) > (1UL << NUM_INITIAL_PT_LOG2)) reply(myself->stack_top()); - utcb->mtd = 0; - utcb->set_msg_word(0); - - bool res = utcb->append_item(Obj_crd(obj->exc_pt_sel_client() + event, logcount), 0); - /* one item ever fits on the UTCB */ + bool res = utcb->append_item(Obj_crd(obj->exc_pt_sel_client() + event, + logcount), 0); (void)res; reply(myself->stack_top()); diff --git a/base-nova/src/base/thread/thread_nova.cc b/base-nova/src/base/thread/thread_nova.cc index 6547218ad..4c5b49ef3 100644 --- a/base-nova/src/base/thread/thread_nova.cc +++ b/base-nova/src/base/thread/thread_nova.cc @@ -166,11 +166,11 @@ void Thread_base::start() throw Cpu_session::Thread_creation_failed(); /* request native EC thread cap */ - Genode::Cpu_session_client cpu(env()->cpu_session_cap()); - Native_capability ec_cap = cpu.native_cap(_thread_cap); - if (!ec_cap.valid()) + _tid.ec_sel = cap_selector_allocator()->alloc(); + if (_tid.ec_sel == Native_thread::INVALID_INDEX) throw Cpu_session::Thread_creation_failed(); - _tid.ec_sel = ec_cap.local_name(); + + request_native_ec_cap(_pager_cap, _tid.ec_sel); using namespace Nova; diff --git a/ports/src/vancouver/main.cc b/ports/src/vancouver/main.cc index c77ba02a0..5cc1df631 100644 --- a/ports/src/vancouver/main.cc +++ b/ports/src/vancouver/main.cc @@ -49,7 +49,6 @@ #include #include #include -#include #include /* NOVA includes that come with Genode */ @@ -317,15 +316,7 @@ class Vcpu_thread : Genode::Thread * Request native EC thread cap and put it next to the * SM cap - see Vcpu_dispatcher->sel_sm_ec description */ - - Nova_cpu_connection cpu; - /* Use selector next to SM cap to retrieve EC cap */ - cpu.rcv_window(sel_ec); - - Native_capability ec_cap = cpu.native_cap(_thread_cap); - - if (!ec_cap.valid() || sel_ec != ec_cap.local_name()) - Logging::panic("Could not collocate EC cap"); + request_native_ec_cap(_pager_cap, sel_ec); } void entry() { } @@ -815,47 +806,9 @@ class Vcpu_dispatcher : public Genode::Thread, { using namespace Genode; - /* create new pager object and assign it to the new thread */ - Pager_capability const pager_cap = - env()->rm_session()->add_client(_thread_cap); - - if (!pager_cap.valid()) - throw Cpu_session::Thread_creation_failed(); - - if (env()->cpu_session()->set_pager(_thread_cap, pager_cap)) - throw Cpu_session::Thread_creation_failed(); - - env()->cpu_session()->state(_thread_cap, - Thread_state(false, _tid.exc_pt_sel)); - - addr_t const thread_sp = (addr_t)&_context->stack[-4]; - - if (env()->cpu_session()->start(_thread_cap, 0, thread_sp)) - throw Cpu_session::Thread_creation_failed(); - - /* Request exception portals for vCPU dispatcher */ - for (unsigned i = 0; i < Nova::PT_SEL_PARENT; i++) - request_event_portal(pager_cap, _tid.exc_pt_sel, i); - - request_event_portal(pager_cap, _tid.exc_pt_sel, - Nova::SM_SEL_EC); - request_event_portal(pager_cap, _tid.exc_pt_sel, - Nova::PT_SEL_RECALL); - - /** - * 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) - */ - Genode::Nova_cpu_connection cpu; - Native_capability ec_cap = cpu.native_cap(_thread_cap); - _tid.ec_sel = ec_cap.local_name(); - - /* init utcb of dispatcher thread */ - Nova::Utcb * utcb = reinterpret_cast(&_context->utcb); - utcb->set_msg_word(0); - utcb->crd_xlt = Nova::Crd(0); - utcb->crd_rcv = Nova::Crd(0); + /* request creation of a 'local' EC */ + _tid.ec_sel = Native_thread::INVALID_INDEX - 1; + Thread_base::start(); using namespace Nova;