nova: request native ec cap via pager

Prerequisite to get rid of the base-nova special native_cap method in
cpu_session.

Vancouver/Seoul bootstrap code gets also much simpler.

Issue #478
This commit is contained in:
Alexander Boettcher 2013-09-25 11:53:49 +02:00 committed by Norman Feske
parent d3bcafc4c6
commit dd2e006309
4 changed files with 40 additions and 63 deletions

View File

@ -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_ */

View File

@ -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());

View File

@ -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;

View File

@ -49,7 +49,6 @@
#include <os/alarm.h>
#include <os/synced_interface.h>
#include <timer_session/connection.h>
#include <nova_cpu_session/connection.h>
#include <rtc_session/connection.h>
/* NOVA includes that come with Genode */
@ -317,15 +316,7 @@ class Vcpu_thread : Genode::Thread<STACK_SIZE>
* 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<STACK_SIZE>,
{
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<Nova::Utcb *>(&_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;