diff --git a/base-nova/include/nova/syscall-generic.h b/base-nova/include/nova/syscall-generic.h index 8eefef099f..82e69c1c06 100644 --- a/base-nova/include/nova/syscall-generic.h +++ b/base-nova/include/nova/syscall-generic.h @@ -217,9 +217,11 @@ namespace Nova { return sel_hotspot << 12; } + mword_t addr() const { return base() << BASE_SHIFT; } mword_t base() const { return _query(); } mword_t order() const { return _query(); } bool is_null() const { return (_value & TYPE_MASK) == NULL_CRD_TYPE; } + uint8_t type() const { return _query(); } } __attribute__((packed)); diff --git a/base-nova/src/core/echo.cc b/base-nova/src/core/echo.cc index 809b4d359b..b76c62957c 100644 --- a/base-nova/src/core/echo.cc +++ b/base-nova/src/core/echo.cc @@ -34,7 +34,26 @@ inline void *echo_stack_top() /** * IDC handler for the echo portal, executed by the echo EC - */ static void echo_reply(){ Nova::reply(echo_stack_top()); } + */ +static void echo_reply() +{ + /* collect map information from calling thread, sent as 3 words */ + Nova::Crd snd_rcv(echo()->utcb()->msg[0]); + Nova::mword_t offset = echo()->utcb()->msg[1]; + bool kern_pd = echo()->utcb()->msg[2]; + + /* reset message transfer descriptor */ + echo()->utcb()->set_msg_word(0); + /* append capability-range as message-transfer item */ + bool res = echo()->utcb()->append_item(snd_rcv, offset, kern_pd); + + /* set return code, 0 means failure */ + echo()->utcb()->msg[0] = res; + echo()->utcb()->items += 1; + + /* during reply the mapping will be established */ + Nova::reply(echo_stack_top()); +} Echo::Echo(Genode::addr_t utcb_addr) @@ -56,6 +75,9 @@ Echo::Echo(Genode::addr_t utcb_addr) /* set up echo portal to ourself */ res = create_pt(_pt_sel, pd_sel, _ec_sel, Mtd(0), (mword_t)echo_reply); if (res) { ((void (*)())(res*0x10001UL))(); } + + /* echo thread doesn't receive anything, it transfers items during reply */ + utcb()->crd_rcv = utcb()->crd_xlt = 0; } diff --git a/base-nova/src/core/include/nova_util.h b/base-nova/src/core/include/nova_util.h index 4faee7f25a..e7c72fd61c 100644 --- a/base-nova/src/core/include/nova_util.h +++ b/base-nova/src/core/include/nova_util.h @@ -45,19 +45,28 @@ enum { verbose_local_map = false }; static int map_local(Nova::Utcb *utcb, Nova::Crd src_crd, Nova::Crd dst_crd, bool kern_pd = false) { - /* open receive window at the echo EC */ - echo()->utcb()->crd_rcv = dst_crd; + /* open receive window at current EC */ + utcb->crd_rcv = dst_crd; - /* reset message transfer descriptor */ - utcb->set_msg_word(0); + /* tell echo thread what to map */ + utcb->msg[0] = src_crd.value(); + utcb->msg[1] = 0; + utcb->msg[2] = kern_pd; + utcb->set_msg_word(3); - /* append capability-range as message-transfer item */ - utcb->append_item(src_crd, 0, kern_pd); + /* establish the mapping via a portal traversal during reply phase */ + Nova::uint8_t res = Nova::call(echo()->pt_sel()); + if (res != 0 || utcb->msg_words() != 1 || !utcb->msg[0]) { + PERR("Failure - map_local 0x%lx:%lu:%u->0x%lx:%lu:%u - call result=%x utcb=%x:%lx !!!", + src_crd.addr(), src_crd.order(), src_crd.type(), + dst_crd.addr(), dst_crd.order(), dst_crd.type(), + res, utcb->msg_words(), utcb->msg[0]); + return res > 0 ? res : -1; + } + /* clear receive window */ + utcb->crd_rcv = 0; - /* establish the mapping via a portal traversal */ - if (echo()->pt_sel() == 0) - PWRN("call to pt 0"); - return Nova::call(echo()->pt_sel()); + return 0; }