diff --git a/repos/base-codezero/src/core/include/ipc_pager.h b/repos/base-codezero/src/core/include/ipc_pager.h index dd0c243baf..6e9d387f1f 100644 --- a/repos/base-codezero/src/core/include/ipc_pager.h +++ b/repos/base-codezero/src/core/include/ipc_pager.h @@ -71,7 +71,7 @@ namespace Genode { /** * Special paging server class */ - class Ipc_pager : public Native_capability + class Ipc_pager { private: @@ -96,11 +96,6 @@ namespace Genode { public: - /** - * Constructor - */ - Ipc_pager(); - /** * Wait for a new page fault received as short message IPC */ @@ -141,9 +136,9 @@ namespace Genode { void acknowledge_wakeup(); /** - * Return thread ID of last faulter + * Returns true if the last request was send from a core thread */ - Native_thread_id last() const { return _last; } + bool request_from_core() { return true; } /** * Return badge for faulting thread diff --git a/repos/base-codezero/src/core/ipc_pager.cc b/repos/base-codezero/src/core/ipc_pager.cc deleted file mode 100644 index c7694d2bca..0000000000 --- a/repos/base-codezero/src/core/ipc_pager.cc +++ /dev/null @@ -1,175 +0,0 @@ -/* - * \brief Pager support for Codezero - * \author Norman Feske - * \date 2010-02-16 - */ - -/* - * Copyright (C) 2010-2013 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. - */ - -/* Genode includes */ -#include - -/* Codezero includes */ -#include -#include - - -using namespace Genode; -using namespace Codezero; - -enum { verbose_page_faults = false }; - - -/************************ - ** Page-fault utility ** - ************************/ - -class Fault -{ - public: - - enum Type { READ, WRITE, EXEC, UNKNOWN }; - - private: - - /** - * Translate Codezero page-fault information to generic fault type - * - * \param sr status - * \param pte page-table entry - */ - static Type _fault_type(umword_t sr, umword_t pte) - { - if (is_prefetch_abort(sr)) - return EXEC; - - if ((pte & PTE_PROT_MASK) == (__MAP_USR_RO & PTE_PROT_MASK)) - return WRITE; - - return READ; - } - - Type _type; - umword_t _addr; - umword_t _ip; - - public: - - /** - * Constructor - * - * \param kdata Codezero-specific page-fault information - */ - Fault(struct fault_kdata const &kdata) - : - _type(_fault_type(kdata.fsr, kdata.pte)), - _addr(_type == EXEC ? kdata.faulty_pc : kdata.far), - _ip(kdata.faulty_pc) - { } - - Type type() const { return _type; } - umword_t addr() const { return _addr; } - umword_t ip() const { return _ip; } -}; - - -/** - * Print page-fault information in a human-readable form - */ -inline void print_page_fault(Fault &fault, int from) -{ - printf("page (%s%s%s) fault from %d at pf_addr=%lx, pf_ip=%lx\n", - fault.type() == Fault::READ ? "r" : "-", - fault.type() == Fault::WRITE ? "w" : "-", - fault.type() == Fault::EXEC ? "x" : "-", - from, fault.addr(), fault.ip()); -} - - -/*************** - ** IPC pager ** - ***************/ - -void Ipc_pager::wait_for_fault() -{ - for (;;) { - int ret = l4_receive(L4_ANYTHREAD); - - if (ret < 0) { - PERR("pager: l4_received returned ret=%d", ret); - continue; - } - - umword_t tag = l4_get_tag(); - int faulter_tid = l4_get_sender(); - - if (tag != L4_IPC_TAG_PFAULT) { - PWRN("got an unexpected IPC from %d", faulter_tid); - continue; - } - - /* copy fault information from message registers */ - struct fault_kdata fault_kdata; - for (unsigned i = 0; i < sizeof(fault_kdata_t)/sizeof(umword_t); i++) - ((umword_t *)&fault_kdata)[i] = read_mr(MR_UNUSED_START + i); - - Fault fault(fault_kdata); - - if (verbose_page_faults) - print_page_fault(fault, faulter_tid); - - /* determine corresponding page in our own address space */ - _pf_addr = fault.addr(); - _pf_write = fault.type() == Fault::WRITE; - _pf_ip = fault.ip(); - _last = faulter_tid; - - return; - } -} - - -void Ipc_pager::reply_and_wait_for_fault() -{ - /* install mapping */ - umword_t flags = _reply_mapping.writeable() ? MAP_USR_RW - : MAP_USR_RO; - - /* - * XXX: remove heuristics for mapping device registers. - */ - if (_reply_mapping.from_phys() == 0x10120000 /* LCD */ - || _reply_mapping.from_phys() == 0x10006000 /* keyboard */ - || _reply_mapping.from_phys() == 0x10007000) /* mouse */ - flags = MAP_USR_IO; - - int ret = l4_map((void *)_reply_mapping.from_phys(), - (void *)_reply_mapping.to_virt(), - _reply_mapping.num_pages(), flags, _last); - - /* wake up faulter if mapping succeeded */ - if (ret < 0) - PERR("l4_map returned %d, putting thread %d to sleep", ret, _last); - else - acknowledge_wakeup(); - - /* wait for next page fault */ - wait_for_fault(); -} - - -void Ipc_pager::acknowledge_wakeup() -{ - enum { SUCCESS = 0 }; - l4_set_sender(_last); - l4_ipc_return(SUCCESS); -} - - -Ipc_pager::Ipc_pager() : Native_capability(thread_myself(), 0) { } - diff --git a/repos/base-codezero/src/core/pager.cc b/repos/base-codezero/src/core/pager.cc index 34b66ee0e6..53e98dd077 100644 --- a/repos/base-codezero/src/core/pager.cc +++ b/repos/base-codezero/src/core/pager.cc @@ -1,105 +1,182 @@ /* - * \brief Dummy pager framework + * \brief Pager support for Codezero * \author Norman Feske - * \date 2009-10-02 + * \date 2010-02-16 */ /* - * Copyright (C) 2009-2013 Genode Labs GmbH + * Copyright (C) 2010-2013 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. */ -/* Core includes */ +/* Genode includes */ +#include #include +/* Codezero includes */ +#include +#include + + using namespace Genode; +using namespace Codezero; + +enum { verbose_page_faults = false }; -/********************** - ** Pager activation ** - **********************/ +/************************ + ** Page-fault utility ** + ************************/ -void Pager_activation_base::entry() +class Fault { - Ipc_pager pager; - _cap = pager; - _cap_valid.unlock(); + public: - bool reply = false; + enum Type { READ, WRITE, EXEC, UNKNOWN }; - while (1) { + private: - if (reply) - pager.reply_and_wait_for_fault(); - else - pager.wait_for_fault(); + /** + * Translate Codezero page-fault information to generic fault type + * + * \param sr status + * \param pte page-table entry + */ + static Type _fault_type(umword_t sr, umword_t pte) + { + if (is_prefetch_abort(sr)) + return EXEC; - /* lookup referenced object */ - Object_pool::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0); - Pager_object * obj = _obj; - reply = false; + if ((pte & PTE_PROT_MASK) == (__MAP_USR_RO & PTE_PROT_MASK)) + return WRITE; - /* handle request */ - if (obj) { - reply = !obj->pager(pager); - /* something strange occurred - leave thread in pagefault */ + return READ; + } + + Type _type; + umword_t _addr; + umword_t _ip; + + public: + + /** + * Constructor + * + * \param kdata Codezero-specific page-fault information + */ + Fault(struct fault_kdata const &kdata) + : + _type(_fault_type(kdata.fsr, kdata.pte)), + _addr(_type == EXEC ? kdata.faulty_pc : kdata.far), + _ip(kdata.faulty_pc) + { } + + Type type() const { return _type; } + umword_t addr() const { return _addr; } + umword_t ip() const { return _ip; } +}; + + +/** + * Print page-fault information in a human-readable form + */ +inline void print_page_fault(Fault &fault, int from) +{ + printf("page (%s%s%s) fault from %d at pf_addr=%lx, pf_ip=%lx\n", + fault.type() == Fault::READ ? "r" : "-", + fault.type() == Fault::WRITE ? "w" : "-", + fault.type() == Fault::EXEC ? "x" : "-", + from, fault.addr(), fault.ip()); +} + + +/*************** + ** IPC pager ** + ***************/ + +void Ipc_pager::wait_for_fault() +{ + for (;;) { + int ret = l4_receive(L4_ANYTHREAD); + + if (ret < 0) { + PERR("pager: l4_received returned ret=%d", ret); continue; } - /* - * We got a request from one of cores region-manager sessions - * to answer the pending page fault of a resolved region-manager - * client. Hence, we have to send the page-fault reply to the - * specified thread and answer the call of the region-manager - * session. - * - * When called from a region-manager session, we receive the - * core-local address of the targeted pager object via the - * first message word, which corresponds to the 'fault_ip' - * argument of normal page-fault messages. - */ - obj = reinterpret_cast(pager.fault_ip()); + umword_t tag = l4_get_tag(); + int faulter_tid = l4_get_sender(); - /* send reply to the calling region-manager session */ - pager.acknowledge_wakeup(); + if (tag != L4_IPC_TAG_PFAULT) { + PWRN("got an unexpected IPC from %d", faulter_tid); + continue; + } - /* answer page fault of resolved pager object */ - pager.set_reply_dst(obj->cap()); - pager.acknowledge_wakeup(); + /* copy fault information from message registers */ + struct fault_kdata fault_kdata; + for (unsigned i = 0; i < sizeof(fault_kdata_t)/sizeof(umword_t); i++) + ((umword_t *)&fault_kdata)[i] = read_mr(MR_UNUSED_START + i); + + Fault fault(fault_kdata); + + if (verbose_page_faults) + print_page_fault(fault, faulter_tid); + + /* determine corresponding page in our own address space */ + _pf_addr = fault.addr(); + _pf_write = fault.type() == Fault::WRITE; + _pf_ip = fault.ip(); + _last = faulter_tid; + + return; } } +void Ipc_pager::reply_and_wait_for_fault() +{ + /* install mapping */ + umword_t flags = _reply_mapping.writeable() ? MAP_USR_RW + : MAP_USR_RO; + + /* + * XXX: remove heuristics for mapping device registers. + */ + if (_reply_mapping.from_phys() == 0x10120000 /* LCD */ + || _reply_mapping.from_phys() == 0x10006000 /* keyboard */ + || _reply_mapping.from_phys() == 0x10007000) /* mouse */ + flags = MAP_USR_IO; + + int ret = l4_map((void *)_reply_mapping.from_phys(), + (void *)_reply_mapping.to_virt(), + _reply_mapping.num_pages(), flags, _last); + + /* wake up faulter if mapping succeeded */ + if (ret < 0) + PERR("l4_map returned %d, putting thread %d to sleep", ret, _last); + else + acknowledge_wakeup(); + + /* wait for next page fault */ + wait_for_fault(); +} + + +void Ipc_pager::acknowledge_wakeup() +{ + enum { SUCCESS = 0 }; + l4_set_sender(_last); + l4_ipc_return(SUCCESS); +} + + /********************** ** Pager entrypoint ** **********************/ -Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a) -: _activation(a) -{ _activation->ep(this); } - - -void Pager_entrypoint::dissolve(Pager_object *obj) +Untyped_capability Pager_entrypoint::_manage(Pager_object *obj) { - remove_locked(obj); -} - - -Pager_capability Pager_entrypoint::manage(Pager_object *obj) -{ - /* return invalid capability if no activation is present */ - if (!_activation) return Pager_capability(); - - _activation->cap(); - - Untyped_capability cap = Native_capability(_activation->cap().dst(), obj->badge()); - - /* add server object to object pool */ - obj->cap(cap); - insert(obj); - - /* return capability that uses the object id as badge */ - return reinterpret_cap_cast(cap); + return Untyped_capability(_tid.l4id, obj->badge()); } diff --git a/repos/base-codezero/src/core/target.inc b/repos/base-codezero/src/core/target.inc index 9e724784f6..721ef7c495 100644 --- a/repos/base-codezero/src/core/target.inc +++ b/repos/base-codezero/src/core/target.inc @@ -12,11 +12,11 @@ SRC_CC += cap_session_component.cc \ dump_alloc.cc \ io_mem_session_component.cc \ io_mem_session_support.cc \ - ipc_pager.cc \ irq_session_component.cc \ main.cc \ pager.cc \ - pager_common.cc \ + pager_ep.cc \ + pager_object.cc \ pd_session_component.cc \ platform.cc \ platform_pd.cc \ @@ -58,5 +58,6 @@ vpath dataspace_component.cc $(GEN_CORE_DIR) vpath core_mem_alloc.cc $(GEN_CORE_DIR) vpath dump_alloc.cc $(GEN_CORE_DIR) vpath context_area.cc $(GEN_CORE_DIR) -vpath pager_common.cc $(GEN_CORE_DIR) +vpath pager_ep.cc $(GEN_CORE_DIR) +vpath pager_object.cc $(GEN_CORE_DIR) vpath %.cc $(REP_DIR)/src/core diff --git a/repos/base-fiasco/src/core/include/ipc_pager.h b/repos/base-fiasco/src/core/include/ipc_pager.h index f8576e695d..62d699af4f 100644 --- a/repos/base-fiasco/src/core/include/ipc_pager.h +++ b/repos/base-fiasco/src/core/include/ipc_pager.h @@ -85,7 +85,7 @@ namespace Genode { /** * Special paging server class */ - class Ipc_pager : public Native_capability + class Ipc_pager { private: @@ -96,11 +96,6 @@ namespace Genode { public: - /** - * Constructor - */ - Ipc_pager(); - /** * Wait for a new page fault received as short message IPC */ @@ -144,9 +139,13 @@ namespace Genode { void acknowledge_wakeup(); /** - * Return thread ID of last faulter + * Returns true if the last request was send from a core thread */ - Native_thread_id last() const { return _last; } + bool request_from_core() + { + enum { CORE_TASK_ID = 4 }; + return _last.id.task == CORE_TASK_ID; + } /** * Return badge for faulting thread diff --git a/repos/base-fiasco/src/core/ipc_pager.cc b/repos/base-fiasco/src/core/ipc_pager.cc deleted file mode 100644 index 5451adb292..0000000000 --- a/repos/base-fiasco/src/core/ipc_pager.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* - * \brief Pager support for Fiasco - * \author Christian Helmuth - * \date 2006-06-14 - */ - -/* - * Copyright (C) 2006-2013 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. - */ - -/* Genode includes */ -#include - -/* Core includes */ -#include - -namespace Fiasco { -#include -#include -} - -using namespace Genode; -using namespace Fiasco; - - -void Ipc_pager::wait_for_fault() -{ - l4_msgdope_t result; - - do { - l4_ipc_wait(&_last, - L4_IPC_SHORT_MSG, &_pf_addr, &_pf_ip, - L4_IPC_NEVER, &result); - - if (L4_IPC_IS_ERROR(result)) - PERR("Ipc error %lx", L4_IPC_ERROR(result)); - - } while (L4_IPC_IS_ERROR(result)); -} - - -void Ipc_pager::reply_and_wait_for_fault() -{ - l4_msgdope_t result; - - l4_ipc_reply_and_wait(_last, - L4_IPC_SHORT_FPAGE, _reply_mapping.dst_addr(), - _reply_mapping.fpage().fpage, &_last, - L4_IPC_SHORT_MSG, &_pf_addr, &_pf_ip, - L4_IPC_SEND_TIMEOUT_0, &result); - - if (L4_IPC_IS_ERROR(result)) { - PERR("Ipc error %lx", L4_IPC_ERROR(result)); - - /* ignore all errors and wait for next proper message */ - wait_for_fault(); - } -} - - -void Ipc_pager::acknowledge_wakeup() -{ - /* answer wakeup call from one of core's region-manager sessions */ - l4_msgdope_t result; - l4_ipc_send(_last, L4_IPC_SHORT_MSG, 0, 0, L4_IPC_SEND_TIMEOUT_0, &result); -} - - -Ipc_pager::Ipc_pager() : Native_capability(Fiasco::l4_myself(), 0) { } diff --git a/repos/base-fiasco/src/core/pager.cc b/repos/base-fiasco/src/core/pager.cc index 9e1f8bc30b..2c15cc3767 100644 --- a/repos/base-fiasco/src/core/pager.cc +++ b/repos/base-fiasco/src/core/pager.cc @@ -1,10 +1,7 @@ /* - * \brief Fiasco pager framework - * \author Norman Feske + * \brief Pager support for Fiasco * \author Christian Helmuth - * \date 2006-07-14 - * - * FIXME Isn't this file generic? + * \date 2006-06-14 */ /* @@ -14,7 +11,11 @@ * under the terms of the GNU General Public License version 2. */ +/* Genode includes */ +#include + /* Core includes */ +#include #include namespace Fiasco { @@ -23,101 +24,61 @@ namespace Fiasco { } using namespace Genode; +using namespace Fiasco; -/********************** - ** Pager activation ** - **********************/ +/*************** + ** Ipc_pager ** + ***************/ -void Pager_activation_base::entry() +void Ipc_pager::wait_for_fault() { - Ipc_pager pager; - _cap = pager; - _cap_valid.unlock(); + l4_msgdope_t result; - Pager_object * obj; - bool reply = false; + do { + l4_ipc_wait(&_last, + L4_IPC_SHORT_MSG, &_pf_addr, &_pf_ip, + L4_IPC_NEVER, &result); - while (1) { + if (L4_IPC_IS_ERROR(result)) + PERR("Ipc error %lx", L4_IPC_ERROR(result)); - if (reply) - pager.reply_and_wait_for_fault(); - else - pager.wait_for_fault(); + } while (L4_IPC_IS_ERROR(result)); +} - /* lookup referenced object */ - Object_pool::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0); - obj = _obj; - reply = false; - /* handle request */ - if (obj) { - reply = !obj->pager(pager); - /* something strange occurred - leave thread in pagefault */ - continue; - } else { +void Ipc_pager::reply_and_wait_for_fault() +{ + l4_msgdope_t result; - /* prevent threads outside of core to mess with our wake-up interface */ - enum { CORE_TASK_ID = 4 }; - if (pager.last().id.task != CORE_TASK_ID) { + l4_ipc_reply_and_wait(_last, + L4_IPC_SHORT_FPAGE, _reply_mapping.dst_addr(), + _reply_mapping.fpage().fpage, &_last, + L4_IPC_SHORT_MSG, &_pf_addr, &_pf_ip, + L4_IPC_SEND_TIMEOUT_0, &result); - PWRN("page fault from unknown partner %x.%02x", - (int)pager.last().id.task, (int)pager.last().id.lthread); + if (L4_IPC_IS_ERROR(result)) { + PERR("Ipc error %lx", L4_IPC_ERROR(result)); - } else { + /* ignore all errors and wait for next proper message */ + wait_for_fault(); + } +} - /* - * We got a request from one of cores region-manager sessions - * to answer the pending page fault of a resolved region-manager - * client. Hence, we have to send the page-fault reply to the - * specified thread and answer the call of the region-manager - * session. - * - * When called from a region-manager session, we receive the - * core-local address of the targeted pager object via the - * first message word, which corresponds to the 'fault_ip' - * argument of normal page-fault messages. - */ - obj = reinterpret_cast(pager.fault_ip()); - /* send reply to the calling region-manager session */ - pager.acknowledge_wakeup(); - - /* answer page fault of resolved pager object */ - pager.set_reply_dst(obj->cap()); - pager.acknowledge_wakeup(); - } - } - }; +void Ipc_pager::acknowledge_wakeup() +{ + /* answer wakeup call from one of core's region-manager sessions */ + l4_msgdope_t result; + l4_ipc_send(_last, L4_IPC_SHORT_MSG, 0, 0, L4_IPC_SEND_TIMEOUT_0, &result); } /********************** - ** Pager entrypoint ** + ** Pager Entrypoint ** **********************/ -Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a) -: _activation(a) -{ _activation->ep(this); } - - -void Pager_entrypoint::dissolve(Pager_object *obj) +Untyped_capability Pager_entrypoint::_manage(Pager_object *obj) { - remove_locked(obj); -} - - -Pager_capability Pager_entrypoint::manage(Pager_object *obj) -{ - /* return invalid capability if no activation is present */ - if (!_activation) return Pager_capability(); - - Native_capability cap(_activation->cap().dst(), obj->badge()); - - /* add server object to object pool */ - obj->cap(cap); - insert(obj); - - /* return capability that uses the object id as badge */ - return reinterpret_cap_cast(cap); + return Untyped_capability(_tid.l4id, obj->badge()); } diff --git a/repos/base-fiasco/src/core/target.inc b/repos/base-fiasco/src/core/target.inc index 9f205b361e..3c588bbbe6 100644 --- a/repos/base-fiasco/src/core/target.inc +++ b/repos/base-fiasco/src/core/target.inc @@ -12,12 +12,12 @@ SRC_CC += cap_session_component.cc \ io_mem_session_component.cc \ io_mem_session_support.cc \ io_port_session_component.cc \ - ipc_pager.cc \ irq_session_component.cc \ main.cc \ multiboot_info.cc \ pager.cc \ - pager_common.cc \ + pager_ep.cc \ + pager_object.cc \ pd_session_component.cc \ platform.cc \ platform_pd.cc \ @@ -58,6 +58,7 @@ vpath trace_session_component.cc $(GEN_CORE_DIR) vpath dataspace_component.cc $(GEN_CORE_DIR) vpath dump_alloc.cc $(GEN_CORE_DIR) vpath context_area.cc $(GEN_CORE_DIR) -vpath pager_common.cc $(GEN_CORE_DIR) +vpath pager_object.cc $(GEN_CORE_DIR) +vpath pager_ep.cc $(GEN_CORE_DIR) vpath core_printf.cc $(BASE_DIR)/src/base/console vpath %.cc $(REP_DIR)/src/core diff --git a/repos/base-foc/src/core/pager.cc b/repos/base-foc/src/core/pager.cc index 9b646bf8f9..1d82bc3224 100644 --- a/repos/base-foc/src/core/pager.cc +++ b/repos/base-foc/src/core/pager.cc @@ -4,8 +4,6 @@ * \author Christian Helmuth * \author Stefan Kalkowski * \date 2006-07-14 - * - * FIXME Isn't this file generic? */ /* @@ -32,33 +30,20 @@ namespace Fiasco { using namespace Genode; -/********************** - ** Pager activation ** - **********************/ - -void Pager_activation_base::entry() +void Pager_entrypoint::entry() { - Ipc_pager pager; - _cap = Native_capability(Thread_base::_thread_cap); - _cap_valid.unlock(); - bool reply_pending = false; while (1) { if (reply_pending) - pager.reply_and_wait_for_fault(); + _pager.reply_and_wait_for_fault(); else - pager.wait_for_fault(); + _pager.wait_for_fault(); reply_pending = false; - if (!_ep) { - PWRN("Pager entrypoint not yet defined"); - continue; - } - /* lookup referenced object */ - Object_pool::Guard obj(_ep->lookup_and_lock(pager.badge())); + Object_pool::Guard obj(lookup_and_lock(_pager.badge())); /* the pager_object might be destroyed, while we got the message */ if (!obj) { @@ -66,14 +51,14 @@ void Pager_activation_base::entry() continue; } - switch (pager.msg_type()) { + switch (_pager.msg_type()) { case Ipc_pager::PAGEFAULT: case Ipc_pager::EXCEPTION: { - if (pager.is_exception()) { + if (_pager.is_exception()) { Lock::Guard guard(obj->state.lock); - pager.get_regs(&obj->state); + _pager.get_regs(&obj->state); obj->state.exceptions++; obj->state.in_exception = true; obj->submit_exception_signal(); @@ -81,12 +66,12 @@ void Pager_activation_base::entry() } /* handle request */ - if (obj->pager(pager)) { + if (obj->pager(_pager)) { /* could not resolv - leave thread in pagefault */ PDBG("Could not resolve pf=%p ip=%p", - (void*)pager.fault_addr(), (void*)pager.fault_ip()); + (void*)_pager.fault_addr(), (void*)_pager.fault_ip()); } else { - pager.set_reply_dst(obj->badge()); + _pager.set_reply_dst(obj->badge()); reply_pending = true; continue; } @@ -104,20 +89,20 @@ void Pager_activation_base::entry() */ /* send reply to the caller */ - pager.set_reply_dst(Native_thread()); - pager.acknowledge_wakeup(); + _pager.set_reply_dst(Native_thread()); + _pager.acknowledge_wakeup(); { Lock::Guard guard(obj->state.lock); /* revert exception flag */ obj->state.in_exception = false; /* set new register contents */ - pager.set_regs(obj->state); + _pager.set_regs(obj->state); } /* send wake up message to requested thread */ - pager.set_reply_dst(obj->badge()); - pager.acknowledge_exception(); + _pager.set_reply_dst(obj->badge()); + _pager.acknowledge_exception(); break; } @@ -128,7 +113,7 @@ void Pager_activation_base::entry() case Ipc_pager::PAUSE: { Lock::Guard guard(obj->state.lock); - pager.get_regs(&obj->state); + _pager.get_regs(&obj->state); obj->state.exceptions++; obj->state.in_exception = true; @@ -138,31 +123,19 @@ void Pager_activation_base::entry() * that case we unblock it immediately. */ if (!obj->state.paused) { - pager.set_reply_dst(obj->badge()); + _pager.set_reply_dst(obj->badge()); reply_pending = true; } break; } default: - PERR("Got unknown message type %x!", pager.msg_type()); + PERR("Got unknown message type %x!", _pager.msg_type()); } }; } -/********************** - ** Pager entrypoint ** - **********************/ - -Pager_entrypoint::Pager_entrypoint(Cap_session *cap_session, - Pager_activation_base *a) -: _activation(a), _cap_session(cap_session) -{ - _activation->ep(this); -} - - void Pager_entrypoint::dissolve(Pager_object *obj) { /* cleanup at cap session */ @@ -176,11 +149,7 @@ Pager_capability Pager_entrypoint::manage(Pager_object *obj) { using namespace Fiasco; - /* return invalid capability if no activation is present */ - if (!_activation) return Pager_capability(); - - Native_capability c = _activation->cap(); - Native_capability cap(_cap_session->alloc(c)); + Native_capability cap(_cap_session->alloc({Thread_base::_thread_cap})); /* add server object to object pool */ obj->cap(cap); diff --git a/repos/base-foc/src/core/target.inc b/repos/base-foc/src/core/target.inc index a06c8e9cfc..78a79f0372 100644 --- a/repos/base-foc/src/core/target.inc +++ b/repos/base-foc/src/core/target.inc @@ -19,7 +19,7 @@ SRC_CC += cap_session_component.cc \ main.cc \ multiboot_info.cc \ pager.cc \ - pager_common.cc \ + pager_object.cc \ pd_session_component.cc \ pd_session_extension.cc \ platform.cc \ @@ -59,7 +59,7 @@ vpath rm_session_component.cc $(GEN_CORE_DIR) vpath rom_session_component.cc $(GEN_CORE_DIR) vpath signal_session_component.cc $(GEN_CORE_DIR) vpath trace_session_component.cc $(GEN_CORE_DIR) -vpath pager_common.cc $(GEN_CORE_DIR) +vpath pager_object.cc $(GEN_CORE_DIR) vpath core_printf.cc $(BASE_DIR)/src/base/console vpath %.cc $(REP_DIR)/src/core vpath %.cc $(REP_DIR)/src/base/thread diff --git a/repos/base-hw/src/core/include/pager.h b/repos/base-hw/src/core/include/pager.h index 4249d8afec..75be292002 100644 --- a/repos/base-hw/src/core/include/pager.h +++ b/repos/base-hw/src/core/include/pager.h @@ -47,15 +47,7 @@ namespace Genode */ class Pager_entrypoint; - /** - * A thread that processes one page fault of a pager object at a time - */ - class Pager_activation_base; - - /** - * Pager-activation base with custom stack size - */ - template class Pager_activation; + enum { PAGER_EP_STACK_SIZE = sizeof(addr_t) * 2048 }; } struct Genode::Mapping @@ -198,26 +190,30 @@ class Genode::Pager_object void thread_cap(Thread_capability const & c); }; -class Genode::Pager_activation_base -: public Thread_base, - public Kernel_object, - public Ipc_pager + +class Genode::Pager_entrypoint : public Object_pool, + public Thread, + public Kernel_object, + public Ipc_pager { - private: - - Lock _startup_lock; - Pager_entrypoint * _ep; - public: /** * Constructor * - * \param name name of the new thread - * \param stack_size stack size of the new thread + * \param a activation that shall handle the objects of the entrypoint */ - Pager_activation_base(char const * const name, - size_t const stack_size); + Pager_entrypoint(Cap_session * cap_session); + + /** + * Associate pager object 'obj' with entry point + */ + Pager_capability manage(Pager_object * const obj); + + /** + * Dissolve pager object 'obj' from entry point + */ + void dissolve(Pager_object * const obj); /** * Bring current mapping data into effect @@ -233,55 +229,6 @@ class Genode::Pager_activation_base **********************/ void entry(); - - - /*************** - ** Accessors ** - ***************/ - - void ep(Pager_entrypoint * const ep); -}; - -class Genode::Pager_entrypoint : public Object_pool -{ - private: - - Pager_activation_base * const _activation; - - public: - - /** - * Constructor - * - * \param a activation that shall handle the objects of the entrypoint - */ - Pager_entrypoint(Cap_session *, Pager_activation_base * const a); - - /** - * Associate pager object 'obj' with entry point - */ - Pager_capability manage(Pager_object * const obj); - - /** - * Dissolve pager object 'obj' from entry point - */ - void dissolve(Pager_object * const obj); -}; - -template -class Genode::Pager_activation : public Pager_activation_base -{ - public: - - /** - * Constructor - */ - Pager_activation() - : - Pager_activation_base("pager_activation", STACK_SIZE) - { - start(); - } }; #endif /* _CORE__INCLUDE__PAGER_H_ */ diff --git a/repos/base-hw/src/core/pager.cc b/repos/base-hw/src/core/pager.cc index 2fd3389584..a2160c1ebf 100644 --- a/repos/base-hw/src/core/pager.cc +++ b/repos/base-hw/src/core/pager.cc @@ -97,21 +97,6 @@ Pager_object::Pager_object(unsigned const badge, Affinity::Location) { } -/*************************** - ** Pager_activation_base ** - ***************************/ - -void Pager_activation_base::ep(Pager_entrypoint * const ep) { _ep = ep; } - - -Pager_activation_base::Pager_activation_base(char const * const name, - size_t const stack_size) -: Thread_base(0, name, stack_size), - Kernel_object(true), - _startup_lock(Lock::LOCKED), _ep(0) -{ } - - /********************** ** Pager_entrypoint ** **********************/ @@ -122,15 +107,16 @@ void Pager_entrypoint::dissolve(Pager_object * const o) } -Pager_entrypoint::Pager_entrypoint(Cap_session *, - Pager_activation_base * const activation) -: _activation(activation) { - _activation->ep(this); } +Pager_entrypoint::Pager_entrypoint(Cap_session *) +: Thread("pager_ep"), + Kernel_object(true) +{ start(); } Pager_capability Pager_entrypoint::manage(Pager_object * const o) { - o->start_paging(_activation->kernel_object()); + o->start_paging(kernel_object()); insert(o); return reinterpret_cap_cast(o->cap()); } + diff --git a/repos/base-hw/src/core/rm_session_support.cc b/repos/base-hw/src/core/rm_session_support.cc index 0400b0beca..2f73037bb8 100644 --- a/repos/base-hw/src/core/rm_session_support.cc +++ b/repos/base-hw/src/core/rm_session_support.cc @@ -36,11 +36,11 @@ void Rm_client::unmap(addr_t, addr_t virt_base, size_t size) } -/*************************** - ** Pager_activation_base ** - ***************************/ +/********************** + ** Pager_entrypoint ** + **********************/ -int Pager_activation_base::apply_mapping() +int Pager_entrypoint::apply_mapping() { Page_flags const flags = Page_flags::apply_mapping(_mapping.writable, @@ -54,10 +54,8 @@ int Pager_activation_base::apply_mapping() } -void Pager_activation_base::entry() +void Pager_entrypoint::entry() { - /* get ready to receive faults */ - _startup_lock.unlock(); while (1) { /* receive fault */ @@ -71,7 +69,7 @@ void Pager_activation_base::entry() * FIXME: The implicit lookup of the oject isn't needed. */ unsigned const pon = po->cap().local_name(); - Object_pool::Guard pog(_ep->lookup_and_lock(pon)); + Object_pool::Guard pog(lookup_and_lock(pon)); if (!pog) continue; /* fetch fault data */ diff --git a/repos/base-linux/src/core/include/pager.h b/repos/base-linux/src/core/include/pager.h index 4eedab99ea..8bcafa6d67 100644 --- a/repos/base-linux/src/core/include/pager.h +++ b/repos/base-linux/src/core/include/pager.h @@ -45,14 +45,12 @@ namespace Genode { void release() { } }; - class Pager_activation_base { }; struct Pager_entrypoint { - Pager_entrypoint(Cap_session *, Pager_activation_base *) { } + Pager_entrypoint(Cap_session *) { } Pager_object *lookup_and_lock(Pager_capability) { return 0; } }; - template class Pager_activation : public Pager_activation_base { }; } #endif /* _CORE__INCLUDE__PAGER_H_ */ diff --git a/repos/base-nova/src/core/include/pager.h b/repos/base-nova/src/core/include/pager.h index 84c43ccb78..556990f82a 100644 --- a/repos/base-nova/src/core/include/pager.h +++ b/repos/base-nova/src/core/include/pager.h @@ -379,9 +379,8 @@ namespace Genode { * \param cap_session Cap_session for creating capabilities * for the pager objects managed by this * entry point - * \param a initial activation */ - Pager_entrypoint(Cap_session *cap_session, Pager_activation_base *a = 0); + Pager_entrypoint(Cap_session *cap_session); /** * Associate Pager_object with the entry point diff --git a/repos/base-nova/src/core/pager.cc b/repos/base-nova/src/core/pager.cc index cf2d19b418..9b26741081 100644 --- a/repos/base-nova/src/core/pager.cc +++ b/repos/base-nova/src/core/pager.cc @@ -620,9 +620,8 @@ void Pager_activation_base::entry() { } **********************/ -Pager_entrypoint::Pager_entrypoint(Cap_session *cap_session, - Pager_activation_base *a) -: _activation(a), _cap_session(cap_session) +Pager_entrypoint::Pager_entrypoint(Cap_session *cap_session) +: _cap_session(cap_session) { /* sanity check space for pager threads */ if (kernel_hip()->cpu_max() > PAGER_CPUS) { @@ -631,20 +630,11 @@ Pager_entrypoint::Pager_entrypoint(Cap_session *cap_session, nova_die(); } - /* determine boot cpu */ - unsigned master_cpu = boot_cpu(); - /* detect enabled CPUs and create per CPU a pager thread */ typedef Pager_activation Pager; Pager * pager_of_cpu = reinterpret_cast(&pager_activation_mem); for (unsigned i = 0; i < kernel_hip()->cpu_max(); i++, pager_of_cpu++) { - if (i == master_cpu) { - pager_threads[master_cpu] = a; - a->ep(this); - continue; - } - if (!kernel_hip()->is_cpu_enabled(i)) continue; diff --git a/repos/base-okl4/src/core/include/ipc_pager.h b/repos/base-okl4/src/core/include/ipc_pager.h index 4654c83b77..0a55bd7fd8 100644 --- a/repos/base-okl4/src/core/include/ipc_pager.h +++ b/repos/base-okl4/src/core/include/ipc_pager.h @@ -73,7 +73,7 @@ namespace Genode { /** * Special paging server class */ - class Ipc_pager : public Native_capability + class Ipc_pager { private: @@ -99,11 +99,6 @@ namespace Genode { public: - /** - * Constructor - */ - Ipc_pager(); - /** * Wait for a new fault received as short message IPC */ @@ -147,14 +142,13 @@ namespace Genode { void acknowledge_wakeup(); /** - * Return thread ID of last faulter + * Returns true if the last request was send from a core thread */ - Native_thread_id last() const { return _last; } - - /** - * Return address space where the last page fault occurred - */ - unsigned long last_space() const { return _last_space; } + bool request_from_core() const + { + enum { CORE_SPACE = 0 }; + return _last_space == CORE_SPACE; + } /** * Return badge for faulting thread diff --git a/repos/base-okl4/src/core/ipc_pager.cc b/repos/base-okl4/src/core/ipc_pager.cc deleted file mode 100644 index 7314b08ef9..0000000000 --- a/repos/base-okl4/src/core/ipc_pager.cc +++ /dev/null @@ -1,148 +0,0 @@ -/* - * \brief Pager support for OKL4 - * \author Norman Feske - * \date 2009-03-31 - */ - -/* - * Copyright (C) 2009-2013 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. - */ - -/* Genode includes */ -#include - -/* Core includes */ -#include - -namespace Okl4 { extern "C" { -#include -#include -#include -#include -} } - -static const bool verbose_page_fault = false; -static const bool verbose_exception = false; - - -using namespace Genode; -using namespace Okl4; - -/** - * Print page-fault information in a human-readable form - */ -static inline void print_page_fault(L4_Word_t type, L4_Word_t addr, L4_Word_t ip, - unsigned long badge) -{ - printf("page (%s%s%s) fault at fault_addr=%lx, fault_ip=%lx, from=%lx\n", - type & L4_Readable ? "r" : "-", - type & L4_Writable ? "w" : "-", - type & L4_eXecutable ? "x" : "-", - addr, ip, badge); -} - - -/** - * Return the global thread ID of the calling thread - * - * On OKL4 we cannot use 'L4_Myself()' to determine our own thread's - * identity. By convention, each thread stores its global ID in a - * defined entry of its UTCB. - */ -static inline Okl4::L4_ThreadId_t thread_get_my_global_id() -{ - Okl4::L4_ThreadId_t myself; - myself.raw = Okl4::__L4_TCR_ThreadWord(UTCB_TCR_THREAD_WORD_MYSELF); - return myself; -} - - -/************* - ** Mapping ** - *************/ - -Mapping::Mapping(addr_t dst_addr, addr_t src_addr, - Cache_attribute cacheability, bool io_mem, - unsigned l2size, bool rw) -: - _fpage(L4_FpageLog2(dst_addr, l2size)), - /* - * OKL4 does not support write-combining as mapping attribute. - */ - _phys_desc(L4_PhysDesc(src_addr, 0)) -{ - L4_Set_Rights(&_fpage, rw ? L4_ReadWriteOnly : L4_ReadeXecOnly); -} - - -Mapping::Mapping() { } - - -/*************** - ** IPC pager ** - ***************/ - -void Ipc_pager::wait_for_fault() -{ - /* wait for fault */ - _faulter_tag = L4_Wait(&_last); - - /* - * Read fault information - */ - - /* exception */ - if (is_exception()) { - L4_StoreMR(1, &_fault_ip); - - if (verbose_exception) - PERR("Exception (label 0x%x) occured in space %d at IP 0x%p", - (int)L4_Label(_faulter_tag), (int)L4_SenderSpace().raw, - (void *)_fault_ip); - } - - /* page fault */ - else { - L4_StoreMR(1, &_fault_addr); - L4_StoreMR(2, &_fault_ip); - - if (verbose_page_fault) - print_page_fault(L4_Label(_faulter_tag), _fault_addr, _fault_ip, _last.raw); - } - _last_space = L4_SenderSpace().raw; -} - - -void Ipc_pager::reply_and_wait_for_fault() -{ - L4_SpaceId_t to_space; - to_space.raw = L4_ThreadNo(_last) >> Thread_id_bits::THREAD; - - /* map page to faulting space */ - int ret = L4_MapFpage(to_space, _reply_mapping.fpage(), - _reply_mapping.phys_desc()); - - if (ret != 1) - PERR("L4_MapFpage returned %d, error_code=%d", - ret, (int)L4_ErrorCode()); - - /* reply to page-fault message to resume the faulting thread */ - acknowledge_wakeup(); - - wait_for_fault(); -} - - -void Ipc_pager::acknowledge_wakeup() -{ - /* answer wakeup call from one of core's region-manager sessions */ - L4_LoadMR(0, 0); - L4_Send(_last); -} - - -Ipc_pager::Ipc_pager() : Native_capability(thread_get_my_global_id(), 0) { } - diff --git a/repos/base-okl4/src/core/pager.cc b/repos/base-okl4/src/core/pager.cc index d1e28953f3..07dc0ff478 100644 --- a/repos/base-okl4/src/core/pager.cc +++ b/repos/base-okl4/src/core/pager.cc @@ -1,5 +1,5 @@ /* - * \brief OKL4-specific pager framework + * \brief Pager support for OKL4 * \author Norman Feske * \date 2009-03-31 */ @@ -11,85 +11,137 @@ * under the terms of the GNU General Public License version 2. */ +/* Genode includes */ +#include + /* Core includes */ +#include #include +namespace Okl4 { extern "C" { +#include +#include +#include +#include +} } + +static const bool verbose_page_fault = false; +static const bool verbose_exception = false; + + using namespace Genode; +using namespace Okl4; - -/********************** - ** Pager activation ** - **********************/ - -void Pager_activation_base::entry() +/** + * Print page-fault information in a human-readable form + */ +static inline void print_page_fault(L4_Word_t type, L4_Word_t addr, L4_Word_t ip, + unsigned long badge) { - Ipc_pager pager; - _cap = pager; - _cap_valid.unlock(); + printf("page (%s%s%s) fault at fault_addr=%lx, fault_ip=%lx, from=%lx\n", + type & L4_Readable ? "r" : "-", + type & L4_Writable ? "w" : "-", + type & L4_eXecutable ? "x" : "-", + addr, ip, badge); +} - bool reply_pending = false; - while (1) { - if (reply_pending) - pager.reply_and_wait_for_fault(); - else - pager.wait_for_fault(); +/** + * Return the global thread ID of the calling thread + * + * On OKL4 we cannot use 'L4_Myself()' to determine our own thread's + * identity. By convention, each thread stores its global ID in a + * defined entry of its UTCB. + */ +static inline Okl4::L4_ThreadId_t thread_get_my_global_id() +{ + Okl4::L4_ThreadId_t myself; + myself.raw = Okl4::__L4_TCR_ThreadWord(UTCB_TCR_THREAD_WORD_MYSELF); + return myself; +} - reply_pending = false; - /* lookup referenced object */ - Object_pool::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0); - Pager_object *obj = _obj; +/************* + ** Mapping ** + *************/ - /* handle request */ - if (obj) { - if (pager.is_exception()) { - obj->submit_exception_signal(); - continue; - } +Mapping::Mapping(addr_t dst_addr, addr_t src_addr, + Cache_attribute cacheability, bool io_mem, + unsigned l2size, bool rw) +: + _fpage(L4_FpageLog2(dst_addr, l2size)), + /* + * OKL4 does not support write-combining as mapping attribute. + */ + _phys_desc(L4_PhysDesc(src_addr, 0)) +{ + L4_Set_Rights(&_fpage, rw ? L4_ReadWriteOnly : L4_ReadeXecOnly); +} - /* send reply if page-fault handling succeeded */ - if (!obj->pager(pager)) - reply_pending = true; - continue; +Mapping::Mapping() { } - } else { - /* - * Prevent threads outside of core to mess with our wake-up - * interface. This condition can trigger if a process gets - * destroyed which triggered a page fault shortly before getting - * killed. In this case, 'wait_for_fault()' returns (because of - * the page fault delivery) but the pager-object lookup will fail - * (because core removed the process already). - */ - enum { CORE_SPACE = 0 }; - if (pager.last_space() == CORE_SPACE) { +/*************** + ** IPC pager ** + ***************/ - /* - * We got a request from one of cores region-manager sessions - * to answer the pending page fault of a resolved region-manager - * client. Hence, we have to send the page-fault reply to the - * specified thread and answer the call of the region-manager - * session. - * - * When called from a region-manager session, we receive the - * core-local address of the targeted pager object via the - * first message word, which corresponds to the 'fault_ip' - * argument of normal page-fault messages. - */ - obj = reinterpret_cast(pager.fault_ip()); +void Ipc_pager::wait_for_fault() +{ + /* wait for fault */ + _faulter_tag = L4_Wait(&_last); - /* send reply to the calling region-manager session */ - pager.acknowledge_wakeup(); + /* + * Read fault information + */ - /* answer page fault of resolved pager object */ - pager.set_reply_dst(obj->cap()); - pager.acknowledge_wakeup(); - } - } - }; + /* exception */ + if (is_exception()) { + L4_StoreMR(1, &_fault_ip); + + if (verbose_exception) + PERR("Exception (label 0x%x) occured in space %d at IP 0x%p", + (int)L4_Label(_faulter_tag), (int)L4_SenderSpace().raw, + (void *)_fault_ip); + } + + /* page fault */ + else { + L4_StoreMR(1, &_fault_addr); + L4_StoreMR(2, &_fault_ip); + + if (verbose_page_fault) + print_page_fault(L4_Label(_faulter_tag), _fault_addr, _fault_ip, _last.raw); + } + _last_space = L4_SenderSpace().raw; +} + + +void Ipc_pager::reply_and_wait_for_fault() +{ + L4_SpaceId_t to_space; + to_space.raw = L4_ThreadNo(_last) >> Thread_id_bits::THREAD; + + /* map page to faulting space */ + int ret = L4_MapFpage(to_space, _reply_mapping.fpage(), + _reply_mapping.phys_desc()); + + if (ret != 1) + PERR("L4_MapFpage returned %d, error_code=%d", + ret, (int)L4_ErrorCode()); + + /* reply to page-fault message to resume the faulting thread */ + acknowledge_wakeup(); + + wait_for_fault(); +} + + +void Ipc_pager::acknowledge_wakeup() +{ + /* answer wakeup call from one of core's region-manager sessions */ + L4_LoadMR(0, 0); + L4_Send(_last); } @@ -97,28 +149,7 @@ void Pager_activation_base::entry() ** Pager entrypoint ** **********************/ -Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a) -: _activation(a) -{ _activation->ep(this); } - - -void Pager_entrypoint::dissolve(Pager_object *obj) +Untyped_capability Pager_entrypoint::_manage(Pager_object *obj) { - remove_locked(obj); -} - - -Pager_capability Pager_entrypoint::manage(Pager_object *obj) -{ - /* return invalid capability if no activation is present */ - if (!_activation) return Pager_capability(); - - Native_capability cap = Native_capability(_activation->cap().dst(), obj->badge()); - - /* add server object to object pool */ - obj->cap(cap); - insert(obj); - - /* return capability that uses the object id as badge */ - return reinterpret_cap_cast(cap); + return Untyped_capability(_tid.l4id, obj->badge()); } diff --git a/repos/base-okl4/src/core/target.inc b/repos/base-okl4/src/core/target.inc index e6c3eac31f..7c42a54d77 100644 --- a/repos/base-okl4/src/core/target.inc +++ b/repos/base-okl4/src/core/target.inc @@ -15,12 +15,12 @@ SRC_CC += cap_session_component.cc \ dump_alloc.cc \ io_mem_session_component.cc \ io_mem_session_support.cc \ - ipc_pager.cc \ irq_session_component.cc \ main.cc \ okl4_pd_session_component.cc \ pager.cc \ - pager_common.cc \ + pager_ep.cc \ + pager_object.cc \ pd_session_component.cc \ platform.cc \ platform_pd.cc \ @@ -61,7 +61,8 @@ vpath dataspace_component.cc $(GEN_CORE_DIR) vpath core_mem_alloc.cc $(GEN_CORE_DIR) vpath dump_alloc.cc $(GEN_CORE_DIR) vpath context_area.cc $(GEN_CORE_DIR) -vpath pager_common.cc $(GEN_CORE_DIR) +vpath pager_ep.cc $(GEN_CORE_DIR) +vpath pager_object.cc $(GEN_CORE_DIR) vpath %.cc $(REP_DIR)/src/core vpath core_printf.cc $(BASE_DIR)/src/base/console diff --git a/repos/base-pistachio/src/core/include/ipc_pager.h b/repos/base-pistachio/src/core/include/ipc_pager.h index 4f5e8b2c2e..36cc7e7a16 100644 --- a/repos/base-pistachio/src/core/include/ipc_pager.h +++ b/repos/base-pistachio/src/core/include/ipc_pager.h @@ -83,7 +83,7 @@ namespace Genode { /** * Special paging server class */ - class Ipc_pager : public Native_capability + class Ipc_pager { private: @@ -108,11 +108,6 @@ namespace Genode { public: - /** - * Constructor - */ - Ipc_pager(); - /** * Wait for a new fault received as short message IPC */ @@ -156,9 +151,9 @@ namespace Genode { void acknowledge_wakeup(); /** - * Return thread ID of last faulter + * Returns true if the last request was send from a core thread */ - Native_thread_id last() const { return _last; } + bool request_from_core() { return true; } /** * Return badge for faulting thread diff --git a/repos/base-pistachio/src/core/ipc_pager.cc b/repos/base-pistachio/src/core/ipc_pager.cc deleted file mode 100644 index 6771a912ac..0000000000 --- a/repos/base-pistachio/src/core/ipc_pager.cc +++ /dev/null @@ -1,141 +0,0 @@ -/* - * \brief Pager support for Pistachio - * \author Christian Helmuth - * \date 2006-06-14 - */ - -/* - * Copyright (C) 2006-2013 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. - */ - -/* Genode includes */ -#include -#include - -/* Core includes */ -#include - -namespace Pistachio -{ -#include -#include -#include -#include -} - -using namespace Genode; -using namespace Pistachio; - - -/************* - ** Mapping ** - *************/ - -Mapping::Mapping(addr_t dst_addr, addr_t src_addr, - Cache_attribute, bool io_mem, unsigned l2size, - bool rw, bool grant) -{ - L4_Fpage_t fpage = L4_FpageLog2(src_addr, l2size); - - fpage += rw ? L4_FullyAccessible : L4_Readable; - - if (grant) - _grant_item = L4_GrantItem(fpage, dst_addr); - else - _map_item = L4_MapItem(fpage, dst_addr); -} - - -Mapping::Mapping() { _map_item = L4_MapItem(L4_Nilpage, 0); } - - -/*************** - ** IPC pager ** - ***************/ - -void Ipc_pager::wait_for_fault() -{ - L4_MsgTag_t result; - L4_ThreadId_t sender = L4_nilthread; - bool failed; - - do { - L4_Accept(L4_UntypedWordsAcceptor); - result = L4_Wait(&sender); - failed = L4_IpcFailed(result); - if (failed) - PERR("Page fault IPC error. (continuable)"); - - if (L4_UntypedWords(result) != 2) { - PERR("Malformed page-fault ipc. (sender = 0x%08lx)", - sender.raw); - failed = true; - } - - } while (failed); - - L4_Msg_t msg; - // TODO Error checking. Did we really receive 2 words? - L4_Store(result, &msg); - - _pf_addr = L4_Get(&msg, 0); - _pf_ip = L4_Get(&msg, 1); - _flags = L4_Label(result); - - _last = sender; -} - - -void Ipc_pager::reply_and_wait_for_fault() -{ - /* - * XXX call memory-control if mapping has enabled write-combining - */ - - L4_Msg_t msg; - L4_Accept(L4_UntypedWordsAcceptor); - L4_Clear(&msg); - - /* this should work even if _map_item is a grant item */ - L4_Append(&msg, _map_item); - L4_Load(&msg); - L4_MsgTag_t result = L4_ReplyWait(_last, &_last); - - if (L4_IpcFailed(result)) { - PERR("Page fault IPC error. (continuable)"); - wait_for_fault(); - return; - } - - if (L4_UntypedWords(result) != 2) { - PERR("Malformed page-fault ipc. (sender = 0x%08lx)", _last.raw); - wait_for_fault(); - return; - } - - L4_Clear(&msg); - // TODO Error checking. Did we really receive 2 words? - L4_Store(result, &msg); - - _pf_addr = L4_Get(&msg, 0); - _pf_ip = L4_Get(&msg, 1); - _flags = L4_Label(result); -} - - -void Ipc_pager::acknowledge_wakeup() -{ - PERR("acknowledge_wakeup called, not yet implemented"); -// /* answer wakeup call from one of core's region-manager sessions */ -// l4_msgdope_t result; -// l4_ipc_send(_last, L4_IPC_SHORT_MSG, 0, 0, L4_IPC_SEND_TIMEOUT_0, &result); -} - - -Ipc_pager::Ipc_pager() -: Native_capability(L4_Myself(), 0) -{ } - diff --git a/repos/base-pistachio/src/core/pager.cc b/repos/base-pistachio/src/core/pager.cc index e6a0461877..a701c564ae 100644 --- a/repos/base-pistachio/src/core/pager.cc +++ b/repos/base-pistachio/src/core/pager.cc @@ -1,10 +1,7 @@ /* - * \brief Pistachio pager framework - * \author Norman Feske + * \brief Pager support for Pistachio * \author Christian Helmuth - * \date 2006-07-14 - * - * FIXME Isn't this file generic? + * \date 2006-06-14 */ /* @@ -14,83 +11,128 @@ * under the terms of the GNU General Public License version 2. */ +/* Genode includes */ +#include +#include + /* Core includes */ +#include #include -using namespace Genode; - - -namespace Pistachio { -#include +namespace Pistachio +{ +#include +#include +#include +#include } -/********************** - ** Pager activation ** - **********************/ +using namespace Genode; +using namespace Pistachio; -void Pager_activation_base::entry() + +/************* + ** Mapping ** + *************/ + +Mapping::Mapping(addr_t dst_addr, addr_t src_addr, + Cache_attribute, bool io_mem, unsigned l2size, + bool rw, bool grant) { - Ipc_pager pager; - _cap = pager; - _cap_valid.unlock(); + L4_Fpage_t fpage = L4_FpageLog2(src_addr, l2size); - Pager_object * obj; - bool reply = false; + fpage += rw ? L4_FullyAccessible : L4_Readable; - while (1) { + if (grant) + _grant_item = L4_GrantItem(fpage, dst_addr); + else + _map_item = L4_MapItem(fpage, dst_addr); +} - if (reply) - pager.reply_and_wait_for_fault(); - else - pager.wait_for_fault(); - /* lookup referenced object */ - Object_pool::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0); - obj = _obj; - reply = false; +Mapping::Mapping() { _map_item = L4_MapItem(L4_Nilpage, 0); } - /* handle request */ - if (obj) { - /* if something strange occurred - leave thread in pagefault */ - reply = !obj->pager(pager); - continue; - } else { - /* prevent threads outside of core to mess with our wake-up interface */ -// enum { CORE_TASK_ID = 4 }; -// if (pager.last().id.task != CORE_TASK_ID) { +/*************** + ** IPC pager ** + ***************/ -#warning Check for messages from outside of core - if (0) { - PWRN("page fault to 0x%08lx from unknown partner %lx.", - Pistachio::L4_Myself().raw, - pager.last().raw); +void Ipc_pager::wait_for_fault() +{ + L4_MsgTag_t result; + L4_ThreadId_t sender = L4_nilthread; + bool failed; - } else { + do { + L4_Accept(L4_UntypedWordsAcceptor); + result = L4_Wait(&sender); + failed = L4_IpcFailed(result); + if (failed) + PERR("Page fault IPC error. (continuable)"); - /* - * We got a request from one of cores region-manager sessions - * to answer the pending page fault of a resolved region-manager - * client. Hence, we have to send the page-fault reply to the - * specified thread and answer the call of the region-manager - * session. - * - * When called from a region-manager session, we receive the - * core-local address of the targeted pager object via the - * first message word, which corresponds to the 'fault_ip' - * argument of normal page-fault messages. - */ - obj = reinterpret_cast(pager.fault_ip()); - - /* send reply to the calling region-manager session */ - pager.acknowledge_wakeup(); - - /* answer page fault of resolved pager object */ - pager.set_reply_dst(obj->cap()); - pager.acknowledge_wakeup(); - } + if (L4_UntypedWords(result) != 2) { + PERR("Malformed page-fault ipc. (sender = 0x%08lx)", + sender.raw); + failed = true; } + + } while (failed); + + L4_Msg_t msg; + // TODO Error checking. Did we really receive 2 words? + L4_Store(result, &msg); + + _pf_addr = L4_Get(&msg, 0); + _pf_ip = L4_Get(&msg, 1); + _flags = L4_Label(result); + + _last = sender; +} + + +void Ipc_pager::reply_and_wait_for_fault() +{ + /* + * XXX call memory-control if mapping has enabled write-combining + */ + + L4_Msg_t msg; + L4_Accept(L4_UntypedWordsAcceptor); + L4_Clear(&msg); + + /* this should work even if _map_item is a grant item */ + L4_Append(&msg, _map_item); + L4_Load(&msg); + L4_MsgTag_t result = L4_ReplyWait(_last, &_last); + + if (L4_IpcFailed(result)) { + PERR("Page fault IPC error. (continuable)"); + wait_for_fault(); + return; } + + if (L4_UntypedWords(result) != 2) { + PERR("Malformed page-fault ipc. (sender = 0x%08lx)", _last.raw); + wait_for_fault(); + return; + } + + L4_Clear(&msg); + // TODO Error checking. Did we really receive 2 words? + L4_Store(result, &msg); + + _pf_addr = L4_Get(&msg, 0); + _pf_ip = L4_Get(&msg, 1); + _flags = L4_Label(result); +} + + +void Ipc_pager::acknowledge_wakeup() +{ + PERR("acknowledge_wakeup called, not yet implemented"); +// /* answer wakeup call from one of core's region-manager sessions */ +// l4_msgdope_t result; +// l4_ipc_send(_last, L4_IPC_SHORT_MSG, 0, 0, L4_IPC_SEND_TIMEOUT_0, &result); } @@ -98,28 +140,7 @@ void Pager_activation_base::entry() ** Pager entrypoint ** **********************/ -Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a) -: _activation(a) -{ _activation->ep(this); } - - -void Pager_entrypoint::dissolve(Pager_object *obj) +Untyped_capability Pager_entrypoint::_manage(Pager_object *obj) { - remove_locked(obj); -} - - -Pager_capability Pager_entrypoint::manage(Pager_object *obj) -{ - /* return invalid capability if no activation is present */ - if (!_activation) return Pager_capability(); - - Native_capability cap = Native_capability(_activation->cap().dst(), obj->badge()); - - /* add server object to object pool */ - obj->cap(cap); - insert(obj); - - /* return capability that uses the object id as badge */ - return reinterpret_cap_cast(cap); + return Untyped_capability(_tid.l4id, obj->badge()); } diff --git a/repos/base-pistachio/src/core/target.inc b/repos/base-pistachio/src/core/target.inc index 3130cf763c..ed9ebf03f0 100644 --- a/repos/base-pistachio/src/core/target.inc +++ b/repos/base-pistachio/src/core/target.inc @@ -13,14 +13,14 @@ SRC_CC = cap_session_component.cc \ dump_alloc.cc \ io_mem_session_component.cc \ io_mem_session_support.cc \ - ipc_pager.cc \ irq_session_component.cc \ kip.cc \ main.cc \ multiboot_info.cc \ pd_session_component.cc \ pager.cc \ - pager_common.cc \ + pager_ep.cc \ + pager_object.cc \ platform.cc \ platform_pd.cc \ platform_services.cc \ @@ -57,7 +57,8 @@ vpath trace_session_component.cc $(GEN_CORE_DIR) vpath dataspace_component.cc $(GEN_CORE_DIR) vpath dump_alloc.cc $(GEN_CORE_DIR) vpath context_area.cc $(GEN_CORE_DIR) -vpath pager_common.cc $(GEN_CORE_DIR) +vpath pager_ep.cc $(GEN_CORE_DIR) +vpath pager_object.cc $(GEN_CORE_DIR) vpath core_printf.cc $(BASE_DIR)/src/base/console vpath kip.cc $(REP_DIR)/src/base/kip vpath %.cc $(REP_DIR)/src/core diff --git a/repos/base-sel4/lib/mk/core.mk b/repos/base-sel4/lib/mk/core.mk index bdea0a7b60..9d22dcb02d 100644 --- a/repos/base-sel4/lib/mk/core.mk +++ b/repos/base-sel4/lib/mk/core.mk @@ -30,7 +30,8 @@ SRC_CC += \ dump_alloc.cc \ context_area.cc \ capability_space.cc \ - pager.cc + pager.cc \ + pager_ep.cc LIBS += core_printf base-common syscall @@ -56,5 +57,6 @@ vpath trace_session_component.cc $(GEN_CORE_DIR) vpath dataspace_component.cc $(GEN_CORE_DIR) vpath core_mem_alloc.cc $(GEN_CORE_DIR) vpath dump_alloc.cc $(GEN_CORE_DIR) +vpath pager_ep.cc $(GEN_CORE_DIR) vpath %.cc $(REP_DIR)/src/core diff --git a/repos/base-sel4/src/core/include/ipc_pager.h b/repos/base-sel4/src/core/include/ipc_pager.h index beaa4bad9e..8e3cccc052 100644 --- a/repos/base-sel4/src/core/include/ipc_pager.h +++ b/repos/base-sel4/src/core/include/ipc_pager.h @@ -129,9 +129,9 @@ namespace Genode { void acknowledge_wakeup(); /** - * Return thread ID of last faulter + * Returns true if the last request was send from a core thread */ - Native_thread_id last() const { return _last; } + bool request_from_core() { return false; } /** * Return badge for faulting thread diff --git a/repos/base-sel4/src/core/pager.cc b/repos/base-sel4/src/core/pager.cc index 1b0b177ee1..1abb2c11e7 100644 --- a/repos/base-sel4/src/core/pager.cc +++ b/repos/base-sel4/src/core/pager.cc @@ -97,51 +97,7 @@ void Ipc_pager::acknowledge_wakeup() } -Ipc_pager::Ipc_pager() -: - Native_capability(Capability_space::create_ep_cap(*Thread_base::myself())), - _last(0) -{ } - - - -/********************** - ** Pager activation ** - **********************/ - -void Pager_activation_base::entry() -{ - Ipc_pager pager; - _cap = pager; - _cap_valid.unlock(); - - bool reply_pending = false; - while (1) { - - if (reply_pending) - pager.reply_and_wait_for_fault(); - else - pager.wait_for_fault(); - - reply_pending = false; - - /* lookup referenced object */ - Object_pool::Guard _obj(_ep ? _ep->lookup_and_lock(pager.badge()) : 0); - Pager_object *obj = _obj; - - /* handle request */ - if (obj) { - if (pager.is_exception()) { - obj->submit_exception_signal(); - continue; - } - - /* send reply if page-fault handling succeeded */ - if (!obj->pager(pager)) - reply_pending = true; - } - } -} +Ipc_pager::Ipc_pager() : _last(0) { } /****************** @@ -164,39 +120,16 @@ void Pager_object::unresolved_page_fault_occurred() ** Pager entrypoint ** **********************/ -Pager_entrypoint::Pager_entrypoint(Cap_session *, Pager_activation_base *a) -: _activation(a) -{ _activation->ep(this); } - - -void Pager_entrypoint::dissolve(Pager_object *obj) +Untyped_capability Pager_entrypoint::_manage(Pager_object *obj) { - remove_locked(obj); -} - - -Pager_capability Pager_entrypoint::manage(Pager_object *obj) -{ - /* return invalid capability if no activation is present */ - if (!_activation) return Pager_capability(); - /* * Create minted endpoint capability of the pager entrypoint. * The badge of the page-fault message is used to find the pager * object for faulted thread. */ - Native_capability ep_cap = _activation->cap(); - Rpc_obj_key rpc_obj_key((addr_t)obj->badge()); - Untyped_capability new_obj_cap = - Capability_space::create_rpc_obj_cap(ep_cap, 0, rpc_obj_key); - - /* add server object to object pool */ - obj->cap(new_obj_cap); - insert(obj); - - return reinterpret_cap_cast(new_obj_cap); + Untyped_capability ep_cap(Capability_space::create_ep_cap(*this)); + return Capability_space::create_rpc_obj_cap(ep_cap, nullptr, rpc_obj_key); } - diff --git a/repos/base/src/core/include/pager.h b/repos/base/src/core/include/pager.h index 85a5ff69c4..5fa003ceb6 100644 --- a/repos/base/src/core/include/pager.h +++ b/repos/base/src/core/include/pager.h @@ -2,11 +2,12 @@ * \brief Paging-server framework * \author Norman Feske * \author Christian Helmuth + * \author Stefan Kalkowski * \date 2006-04-28 */ /* - * Copyright (C) 2006-2013 Genode Labs GmbH + * Copyright (C) 2006-2015 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. @@ -16,31 +17,31 @@ #define _CORE__INCLUDE__PAGER_H_ #include -#include -#include -#include #include -#include #include #include +#include namespace Genode { + /** + * Special server object for paging + * + * A 'Pager_object' is very similar to a 'Rpc_object'. It is just a + * special implementation for page-fault handling, which does not allow to + * define a "badge" for pager capabilities. + */ class Pager_object; + + /** + * Paging entry point + */ class Pager_entrypoint; - class Pager_activation_base; - template class Pager_activation; + + enum { PAGER_EP_STACK_SIZE = sizeof(addr_t) * 2048 }; } - -/** - * Special server object for paging - * - * A 'Pager_object' is very similar to a 'Rpc_object'. It is just a - * special implementation for page-fault handling, which does not allow to - * define a "badge" for pager capabilities. - */ class Genode::Pager_object : public Object_pool::Entry { protected: @@ -125,69 +126,15 @@ class Genode::Pager_object : public Object_pool::Entry }; -/** - * A 'Pager_activation' processes one page fault of a 'Pager_object' at a time. - */ -class Genode::Pager_activation_base: public Thread_base +class Genode::Pager_entrypoint : public Object_pool, + public Thread { private: - enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT }; + Ipc_pager _pager; + Cap_session *_cap_session; - Native_capability _cap; - Pager_entrypoint *_ep; /* entry point to which the - activation belongs */ - /** - * Lock used for blocking until '_cap' is initialized - */ - Lock _cap_valid; - - public: - - Pager_activation_base(const char *name, size_t stack_size) - : Thread_base(WEIGHT, name, stack_size), _cap(Native_capability()), - _ep(0), _cap_valid(Lock::LOCKED) { } - - /** - * Set entry point, which the activation serves - * - * This method is only called by the 'Pager_entrypoint' - * constructor. - */ - void ep(Pager_entrypoint *ep) { _ep = ep; } - - /** - * Thread interface - */ - void entry(); - - /** - * Return capability to this activation - * - * This method should only be called from 'Pager_entrypoint' - */ - Native_capability cap() - { - /* ensure that the initialization of our 'Ipc_pager' is done */ - if (!_cap.valid()) - _cap_valid.lock(); - return _cap; - } -}; - - -/** - * Paging entry point - * - * For a paging entry point can hold only one activation. So, paging is - * strictly serialized for one entry point. - */ -class Genode::Pager_entrypoint : public Object_pool -{ - private: - - Pager_activation_base *_activation; - Cap_session *_cap_session; + Untyped_capability _manage(Pager_object *obj); public: @@ -197,9 +144,10 @@ class Genode::Pager_entrypoint : public Object_pool * \param cap_session Cap_session for creating capabilities * for the pager objects managed by this * entry point - * \param a initial activation */ - Pager_entrypoint(Cap_session *cap_session, Pager_activation_base *a = 0); + Pager_entrypoint(Cap_session *cap_session) + : Thread("pager_ep"), + _cap_session(cap_session) { start(); } /** * Associate Pager_object with the entry point @@ -210,16 +158,13 @@ class Genode::Pager_entrypoint : public Object_pool * Dissolve Pager_object from entry point */ void dissolve(Pager_object *obj); -}; -template -class Genode::Pager_activation : public Pager_activation_base -{ - public: + /********************** + ** Thread interface ** + **********************/ - Pager_activation() : Pager_activation_base("pager", STACK_SIZE) - { start(); } + void entry(); }; #endif /* _CORE__INCLUDE__PAGER_H_ */ diff --git a/repos/base/src/core/include/rm_root.h b/repos/base/src/core/include/rm_root.h index 242ae725b9..a25c2b9fd3 100644 --- a/repos/base/src/core/include/rm_root.h +++ b/repos/base/src/core/include/rm_root.h @@ -29,12 +29,7 @@ namespace Genode { Rpc_entrypoint *_ds_ep; Rpc_entrypoint *_thread_ep; Allocator *_md_alloc; - - enum { PAGER_STACK_SIZE = 2*4096 }; - Pager_activation _pager_thread; - Pager_entrypoint _pager_ep; - addr_t _vm_start; size_t _vm_size; @@ -105,8 +100,8 @@ namespace Genode { : Root_component(session_ep, md_alloc), _ds_ep(ds_ep), _thread_ep(thread_ep), _md_alloc(md_alloc), - _pager_thread(), _pager_ep(cap_session, &_pager_thread), - _vm_start(vm_start), _vm_size(vm_size) { } + _pager_ep(cap_session), _vm_start(vm_start), _vm_size(vm_size) + { } /** * Return pager entrypoint diff --git a/repos/base/src/core/pager_ep.cc b/repos/base/src/core/pager_ep.cc new file mode 100644 index 0000000000..42af9444e2 --- /dev/null +++ b/repos/base/src/core/pager_ep.cc @@ -0,0 +1,103 @@ +/* + * \brief Generic implmentation of pager entrypoint + * \author Norman Feske + * \author Stefan Kalkowski + * \date 2009-03-31 + */ + +/* + * Copyright (C) 2009-2015 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. + */ + +/* Core includes */ +#include + +using namespace Genode; + + +void Pager_entrypoint::entry() +{ + bool reply_pending = false; + + while (1) { + + if (reply_pending) + _pager.reply_and_wait_for_fault(); + else + _pager.wait_for_fault(); + + reply_pending = false; + + /* lookup referenced object */ + Object_pool::Guard _obj(lookup_and_lock(_pager.badge())); + Pager_object *obj = _obj; + + /* handle request */ + if (obj) { + if (_pager.is_exception()) { + obj->submit_exception_signal(); + continue; + } + + /* send reply if page-fault handling succeeded */ + reply_pending = !obj->pager(_pager); + continue; + + } else { + + /* + * Prevent threads outside of core to mess with our wake-up + * interface. This condition can trigger if a process gets + * destroyed which triggered a page fault shortly before getting + * killed. In this case, 'wait_for_fault()' returns (because of + * the page fault delivery) but the pager-object lookup will fail + * (because core removed the process already). + */ + if (_pager.request_from_core()) { + + /* + * We got a request from one of cores region-manager sessions + * to answer the pending page fault of a resolved region-manager + * client. Hence, we have to send the page-fault reply to the + * specified thread and answer the call of the region-manager + * session. + * + * When called from a region-manager session, we receive the + * core-local address of the targeted pager object via the + * first message word, which corresponds to the 'fault_ip' + * argument of normal page-fault messages. + */ + obj = reinterpret_cast(_pager.fault_ip()); + + /* send reply to the calling region-manager session */ + _pager.acknowledge_wakeup(); + + /* answer page fault of resolved pager object */ + _pager.set_reply_dst(obj->cap()); + _pager.acknowledge_wakeup(); + } + } + }; +} + + +void Pager_entrypoint::dissolve(Pager_object *obj) +{ + remove_locked(obj); +} + + +Pager_capability Pager_entrypoint::manage(Pager_object *obj) +{ + Native_capability cap = _manage(obj); + + /* add server object to object pool */ + obj->cap(cap); + insert(obj); + + /* return capability that uses the object id as badge */ + return reinterpret_cap_cast(cap); +} diff --git a/repos/base/src/core/pager_common.cc b/repos/base/src/core/pager_object.cc similarity index 100% rename from repos/base/src/core/pager_common.cc rename to repos/base/src/core/pager_object.cc