From 57949c2bbb163f1238a880f00898d7f3ee397758 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Thu, 10 Nov 2016 11:46:30 +0100 Subject: [PATCH] nova: support asynchronous delegate Issue #2173 --- .../include/spec/32bit/nova/syscalls.h | 7 ++ .../include/spec/64bit/nova/syscalls.h | 7 ++ repos/base-nova/ports/nova.hash | 2 +- repos/base-nova/ports/nova.port | 2 +- repos/base-nova/run/platform.run | 2 +- repos/base-nova/src/core/echo.cc | 13 ++- repos/base-nova/src/core/include/ipc_pager.h | 34 ++++-- repos/base-nova/src/core/include/platform.h | 8 +- .../base-nova/src/core/include/platform_pd.h | 13 --- .../src/core/include/signal_broker.h | 6 +- repos/base-nova/src/core/ipc_pager.cc | 40 +++++-- repos/base-nova/src/core/pager.cc | 101 ++++++++++-------- repos/base-nova/src/core/platform.cc | 19 ++-- repos/base-nova/src/core/platform_thread.cc | 8 +- repos/base-nova/src/core/rpc_cap_factory.cc | 8 +- repos/base-nova/src/core/thread_start.cc | 10 +- repos/base-nova/src/test/platform/main.cc | 36 ++----- .../platform/spec/x86/device_pd/main.cc | 24 +++-- 18 files changed, 194 insertions(+), 146 deletions(-) diff --git a/repos/base-nova/include/spec/32bit/nova/syscalls.h b/repos/base-nova/include/spec/32bit/nova/syscalls.h index 94bad1a928..465192c719 100644 --- a/repos/base-nova/include/spec/32bit/nova/syscalls.h +++ b/repos/base-nova/include/spec/32bit/nova/syscalls.h @@ -339,6 +339,13 @@ namespace Nova { } + ALWAYS_INLINE + inline uint8_t delegate(mword_t pd_snd, mword_t pd_dst, Crd crd_dst) + { + return syscall_2(NOVA_LOOKUP, 1, pd_snd, crd_dst.value(), pd_dst); + } + + ALWAYS_INLINE inline uint8_t sm_ctrl(unsigned sm, Sem_op op, unsigned long long timeout = 0) { diff --git a/repos/base-nova/include/spec/64bit/nova/syscalls.h b/repos/base-nova/include/spec/64bit/nova/syscalls.h index 80c68fb31e..1715271020 100644 --- a/repos/base-nova/include/spec/64bit/nova/syscalls.h +++ b/repos/base-nova/include/spec/64bit/nova/syscalls.h @@ -292,6 +292,13 @@ namespace Nova { } + ALWAYS_INLINE + inline uint8_t delegate(mword_t pd_snd, mword_t pd_dst, Crd crd_dst) + { + return syscall_2(NOVA_LOOKUP, 1, pd_snd, crd_dst.value(), pd_dst); + } + + ALWAYS_INLINE inline uint8_t sm_ctrl(mword_t sm, Sem_op op, unsigned long long timeout = 0) { diff --git a/repos/base-nova/ports/nova.hash b/repos/base-nova/ports/nova.hash index 1464081ed0..f2d9e2f67a 100644 --- a/repos/base-nova/ports/nova.hash +++ b/repos/base-nova/ports/nova.hash @@ -1 +1 @@ -931c26a24d490daae7df7ebbb03274366088adf0 +6f91bce10f8f9faa2a0f57b9d135559a1ce499a7 diff --git a/repos/base-nova/ports/nova.port b/repos/base-nova/ports/nova.port index 1e60bbce86..d62593468c 100644 --- a/repos/base-nova/ports/nova.port +++ b/repos/base-nova/ports/nova.port @@ -4,7 +4,7 @@ DOWNLOADS := nova.git # r9 branch - use r9_debug for more verbose kernel messages URL(nova) := https://github.com/alex-ab/NOVA.git -REV(nova) := 4d6f04dd02d8099a20766025457be0afd0eae534 +REV(nova) := b493eef81a1313f1cd420b4ed4310ef154c79c04 DIR(nova) := src/kernel/nova PATCHES := $(wildcard $(REP_DIR)/patches/*.patch) diff --git a/repos/base-nova/run/platform.run b/repos/base-nova/run/platform.run index 5bc8bd352c..0fd44c5179 100644 --- a/repos/base-nova/run/platform.run +++ b/repos/base-nova/run/platform.run @@ -37,6 +37,6 @@ build_boot_image "core init test-platform" append qemu_args "-nographic -m 128 -smp 2" -run_genode_until {Test finished} 150 +run_genode_until {Test finished} 200 puts "\nTest succeeded" diff --git a/repos/base-nova/src/core/echo.cc b/repos/base-nova/src/core/echo.cc index 83ede70e06..6b72880168 100644 --- a/repos/base-nova/src/core/echo.cc +++ b/repos/base-nova/src/core/echo.cc @@ -12,8 +12,8 @@ * under the terms of the GNU General Public License version 2. */ -/* Core includes */ -#include +/* core-local includes */ +#include /* local includes */ #include @@ -69,9 +69,12 @@ Echo::Echo(Genode::addr_t utcb_addr) { using namespace Nova; + extern Genode::addr_t __initial_sp; + Hip const * const hip = reinterpret_cast(__initial_sp); + /* create echo EC */ - Genode::addr_t pd_sel = Genode::Platform_pd::pd_core_sel(); - uint8_t res = create_ec(_ec_sel, pd_sel, boot_cpu(), utcb_addr, + Genode::addr_t const core_pd_sel = hip->sel_exc; + uint8_t res = create_ec(_ec_sel, core_pd_sel, boot_cpu(), utcb_addr, reinterpret_cast(echo_stack_top()), ECHO_EXC_BASE, ECHO_GLOBAL); @@ -79,7 +82,7 @@ Echo::Echo(Genode::addr_t utcb_addr) if (res != Nova::NOVA_OK) { *reinterpret_cast(0) = 0xdead; } /* set up echo portal to ourself */ - res = create_pt(_pt_sel, pd_sel, _ec_sel, Mtd(0), (mword_t)echo_reply); + res = create_pt(_pt_sel, core_pd_sel, _ec_sel, Mtd(0), (mword_t)echo_reply); if (res != Nova::NOVA_OK) { *reinterpret_cast(0) = 0xdead; } revoke(Obj_crd(_pt_sel, 0, Obj_crd::RIGHT_PT_CTRL)); diff --git a/repos/base-nova/src/core/include/ipc_pager.h b/repos/base-nova/src/core/include/ipc_pager.h index a810ac7e97..a36cef5010 100644 --- a/repos/base-nova/src/core/include/ipc_pager.h +++ b/repos/base-nova/src/core/include/ipc_pager.h @@ -75,12 +75,19 @@ namespace Genode { { private: + addr_t _pd_dst; + addr_t _pd_core; addr_t _fault_ip; addr_t _fault_addr; + addr_t _sp; uint8_t _fault_type; + uint8_t _syscall_res; + uint8_t _normal_ipc; public: + Ipc_pager (Nova::Utcb *, addr_t pd_dst, addr_t pd_core); + /* * Intel manual: 6.15 EXCEPTION AND INTERRUPT REFERENCE * Interrupt 14—Page-Fault Exception (#PF) @@ -93,18 +100,10 @@ namespace Genode { ERR_P = 1 << 0, }; - /** - * Wait for page-fault info - * - * After returning from this call, 'fault_ip' and 'fault_addr' - * have a defined state. - */ - void wait_for_fault(); - /** * Answer current page fault */ - void reply_and_wait_for_fault(unsigned sm = 0); + void reply_and_wait_for_fault(addr_t sm = 0UL); /** * Request instruction pointer of current fault @@ -136,6 +135,23 @@ namespace Genode { */ return false; } + + /** + * Return result of delegate syscall + */ + uint8_t syscall_result() const { return _syscall_res; } + + /** + * Return low level fault type info + * Intel manual: 6.15 EXCEPTION AND INTERRUPT REFERENCE + * Interrupt 14—Page-Fault Exception (#PF) + */ + addr_t fault_type() { return _fault_type; } + + /** + * Return stack pointer address valid during page-fault + */ + addr_t sp() { return _sp; } }; } diff --git a/repos/base-nova/src/core/include/platform.h b/repos/base-nova/src/core/include/platform.h index 81bea3eee3..618ed803ec 100644 --- a/repos/base-nova/src/core/include/platform.h +++ b/repos/base-nova/src/core/include/platform.h @@ -34,7 +34,8 @@ namespace Genode { Phys_allocator _io_port_alloc; /* I/O port allocator */ Phys_allocator _irq_alloc; /* IRQ allocator */ Rom_fs _rom_fs; /* ROM file system */ - int _gsi_base_sel; /* cap selector of 1st IRQ */ + unsigned _gsi_base_sel; /* cap selector of 1st IRQ */ + unsigned _core_pd_sel; /* cap selector of root PD */ /** * Virtual address range usable by non-core processes @@ -100,6 +101,11 @@ namespace Genode { * Return kernel CPU ID for given Genode CPU */ unsigned kernel_cpu_id(unsigned genode_cpu_id); + + /** + * PD kernel capability selector of core + */ + unsigned core_pd_sel() const { return _core_pd_sel; } }; } diff --git a/repos/base-nova/src/core/include/platform_pd.h b/repos/base-nova/src/core/include/platform_pd.h index 24ead2097a..0a7bc7a520 100644 --- a/repos/base-nova/src/core/include/platform_pd.h +++ b/repos/base-nova/src/core/include/platform_pd.h @@ -18,11 +18,6 @@ #include #include -/* - * Must be initialized by the startup code, - * only valid in core - */ -extern Genode::addr_t __core_pd_sel; namespace Genode { @@ -83,14 +78,6 @@ namespace Genode { */ addr_t pd_sel() const { return _pd_sel; } - /** - * Capability selector of core protection domain - * - * \return PD selector - */ - static addr_t pd_core_sel() { return __core_pd_sel; } - - /** * Label of this protection domain * diff --git a/repos/base-nova/src/core/include/signal_broker.h b/repos/base-nova/src/core/include/signal_broker.h index 6ea1f9d81d..b57b6ba1d6 100644 --- a/repos/base-nova/src/core/include/signal_broker.h +++ b/repos/base-nova/src/core/include/signal_broker.h @@ -21,6 +21,7 @@ #include /* core-local includes */ +#include #include #include @@ -91,8 +92,9 @@ class Genode::Signal_broker Native_capability si = Capability_space::import(cap_map()->insert()); Signal_context_capability cap = reinterpret_cap_cast(si); - uint8_t res = Nova::create_si(cap.local_name(), __core_pd_sel, imprint, - sm.local_name()); + uint8_t res = Nova::create_si(cap.local_name(), + platform_specific()->core_pd_sel(), + imprint, sm.local_name()); if (res != Nova::NOVA_OK) { warning("creating signal failed - error ", res); return Signal_context_capability(); diff --git a/repos/base-nova/src/core/ipc_pager.cc b/repos/base-nova/src/core/ipc_pager.cc index 414b7a4b9a..eb706798ae 100644 --- a/repos/base-nova/src/core/ipc_pager.cc +++ b/repos/base-nova/src/core/ipc_pager.cc @@ -23,17 +23,24 @@ using namespace Genode; -void Ipc_pager::wait_for_fault() +Ipc_pager::Ipc_pager(Nova::Utcb * utcb, addr_t pd_dst, addr_t pd_core) +: + _pd_dst(pd_dst), + _pd_core(pd_core), + _fault_ip(utcb->ip), + _fault_addr(utcb->qual[1]), + _sp(utcb->sp), + _fault_type(utcb->qual[0]), + _syscall_res(Nova::NOVA_OK), + _normal_ipc((((addr_t)&utcb->qual[2] - (addr_t)utcb->msg) / sizeof(addr_t)) + == utcb->msg_words()) { + /* * When this function is called from the page-fault handler EC, a page * fault already occurred. So we never wait but immediately read the * page-fault information from our UTCB. */ - Nova::Utcb *utcb = (Nova::Utcb *)Thread::myself()->utcb(); - _fault_type = utcb->qual[0]; - _fault_addr = utcb->qual[1]; - _fault_ip = utcb->ip; } @@ -41,14 +48,31 @@ void Ipc_pager::set_reply_mapping(Mapping m) { Nova::Utcb *utcb = (Nova::Utcb *)Thread::myself()->utcb(); utcb->set_msg_word(0); - bool res = utcb->append_item(m.mem_crd(), m.dst_addr(), true, false, + bool res = utcb->append_item(m.mem_crd(), 0, true, false, false, m.dma(), m.write_combined()); /* one item ever fits on the UTCB */ (void)res; + + /* receive window in destination pd */ + Nova::Mem_crd crd_mem(m.dst_addr() >> 12, m.mem_crd().order(), + Nova::Rights(true, true, true)); + /* asynchronously map memory */ + _syscall_res = Nova::delegate(_pd_core, _pd_dst, crd_mem); } -void Ipc_pager::reply_and_wait_for_fault(unsigned sm) +void Ipc_pager::reply_and_wait_for_fault(addr_t sm) { - Nova::reply(Thread::myself()->stack_top(), sm); + Thread * myself = Thread::myself(); + Nova::Utcb * utcb = reinterpret_cast(myself->utcb()); + + utcb->mtd = 0; + + /* + * If it was a normal IPC and the mapping failed, caller may re-try. + * Otherwise nothing left to be delegated - done asynchronously beforehand. + */ + utcb->set_msg_word((_normal_ipc && _syscall_res != Nova::NOVA_OK) ? 1 : 0); + + Nova::reply(myself->stack_top(), sm); } diff --git a/repos/base-nova/src/core/pager.cc b/repos/base-nova/src/core/pager.cc index b0fcc4c1dd..3c00d889f8 100644 --- a/repos/base-nova/src/core/pager.cc +++ b/repos/base-nova/src/core/pager.cc @@ -36,7 +36,6 @@ static bool verbose_oom = false; using namespace Genode; using namespace Nova; -extern Genode::addr_t __core_pd_sel; static Nova::Hip * kernel_hip() { @@ -79,11 +78,13 @@ struct Page_fault_info char const * const pd; char const * const thread; unsigned const cpu; - addr_t const ip, addr; + addr_t const ip, addr, sp; + uint8_t const pf_type; Page_fault_info(char const *pd, char const *thread, unsigned cpu, - addr_t ip, addr_t addr) - : pd(pd), thread(thread), cpu(cpu), ip(ip), addr(addr) { } + addr_t ip, addr_t addr, addr_t sp, unsigned type) + : pd(pd), thread(thread), cpu(cpu), ip(ip), addr(addr), + sp(sp), pf_type(type) { } void print(Genode::Output &out) const { @@ -91,32 +92,57 @@ struct Page_fault_info "thread='", thread, "' " "cpu=", cpu, " " "ip=", Hex(ip), " " - "address=", Hex(addr)); + "address=", Hex(addr), " " + "stack pointer=", Hex(sp), " " + "qualifiers=", Hex(pf_type), " ", + pf_type & Ipc_pager::ERR_I ? "I" : "i", + pf_type & Ipc_pager::ERR_R ? "R" : "r", + pf_type & Ipc_pager::ERR_U ? "U" : "u", + pf_type & Ipc_pager::ERR_W ? "W" : "w", + pf_type & Ipc_pager::ERR_P ? "P" : "p"); } }; void Pager_object::_page_fault_handler(addr_t pager_obj) { - Ipc_pager ipc_pager; - ipc_pager.wait_for_fault(); - Thread * myself = Thread::myself(); Pager_object * obj = reinterpret_cast(pager_obj); Utcb * utcb = reinterpret_cast(myself->utcb()); + + Ipc_pager ipc_pager(reinterpret_cast(utcb), obj->pd_sel(), + platform_specific()->core_pd_sel()); + Pager_activation_base * pager_thread = static_cast(myself); /* lookup fault address and decide what to do */ - int ret = obj->pager(ipc_pager); + int error = obj->pager(ipc_pager); /* don't open receive window for pager threads */ if (utcb->crd_rcv.value()) nova_die(); + if (!error && ipc_pager.syscall_result() != Nova::NOVA_OK) { + /* something went wrong - by default don't answer the page fault */ + error = 4; + + /* dst pd has not enough kernel quota ? - try to recover */ + if (ipc_pager.syscall_result() == Nova::NOVA_PD_OOM) { + uint8_t res = obj->handle_oom(); + if (res == Nova::NOVA_PD_OOM) + /* block until revoke is due */ + ipc_pager.reply_and_wait_for_fault(obj->sel_sm_block_oom()); + else if (res == Nova::NOVA_OK) + /* succeeded to recover - continue normally */ + error = 0; + } + } + /* good case - found a valid region which is mappable */ - if (!ret) + if (!error) ipc_pager.reply_and_wait_for_fault(); + obj->_state_lock.lock(); obj->_state.thread.ip = ipc_pager.fault_ip(); @@ -132,33 +158,16 @@ void Pager_object::_page_fault_handler(addr_t pager_obj) Page_fault_info const fault_info(client_pd, client_thread, which_cpu(pager_thread), - ipc_pager.fault_ip(), ipc_pager.fault_addr()); + ipc_pager.fault_ip(), + ipc_pager.fault_addr(), + ipc_pager.sp(), + ipc_pager.fault_type()); /* region manager fault - to be handled */ - if (ret == 1) { - log("page fault, ", fault_info); + log("page fault, ", fault_info, " reason=", error); - utcb->set_msg_word(0); - utcb->mtd = 0; - - /* block the faulting thread until region manager is done */ - ipc_pager.reply_and_wait_for_fault(obj->sel_sm_block_pause()); - } - - /* unhandled case */ - obj->_state.mark_dead(); - - warning("unresolvable page fault, ", fault_info, " ret=", ret); - - Native_capability pager_cap = obj->Object_pool::Entry::cap(); - - revoke(Capability_space::crd(pager_cap).base()); - - revoke(Obj_crd(obj->exc_pt_sel_client(), NUM_INITIAL_PT_LOG2)); - - utcb->set_msg_word(0); - utcb->mtd = 0; - ipc_pager.reply_and_wait_for_fault(); + /* block the faulting thread until region manager is done */ + ipc_pager.reply_and_wait_for_fault(obj->sel_sm_block_pause()); } @@ -364,7 +373,7 @@ void Pager_object::_invoke_handler(addr_t pager_obj) revoke(Obj_crd(obj->exc_pt_sel_client() + PT_SEL_STARTUP, 0)); bool res = Nova::create_sm(obj->exc_pt_sel_client() + PT_SEL_STARTUP, - __core_pd_sel, 0); + platform_specific()->core_pd_sel(), 0); if (res != Nova::NOVA_OK) reply(myself->stack_top()); @@ -524,7 +533,7 @@ void Exception_handlers::register_handler(Pager_object *obj, Mtd mtd, /* compiler generates instance of exception entry if not specified */ addr_t entry = func ? (addr_t)func : (addr_t)(&_handler); uint8_t res = create_portal(obj->exc_pt_sel_client() + EV, - __core_pd_sel, ec_sel, mtd, entry, obj); + platform_specific()->core_pd_sel(), ec_sel, mtd, entry, obj); if (res != Nova::NOVA_OK) throw Region_map::Invalid_thread(); } @@ -589,7 +598,7 @@ Pager_object::Pager_object(Cpu_session_capability cpu_session_cap, { uint8_t res; - addr_t pd_sel = __core_pd_sel; + addr_t const pd_sel = platform_specific()->core_pd_sel(); _state._status = 0; _state.modified = false; _state.sel_client_ec = Native_thread::INVALID_INDEX; @@ -685,13 +694,14 @@ uint8_t Pager_object::handle_oom(addr_t transfer_from, char const * src_pd, char const * src_thread, enum Pager_object::Policy policy) { - const char * dst_pd = client_pd(); - const char * dst_thread = client_thread(); + char const * dst_pd = client_pd(); + char const * dst_thread = client_thread(); + addr_t const core_pd_sel = platform_specific()->core_pd_sel(); enum { QUOTA_TRANSFER_PAGES = 2 }; if (transfer_from == SRC_CORE_PD) - transfer_from = __core_pd_sel; + transfer_from = core_pd_sel; /* request current kernel quota usage of target pd */ addr_t limit_before = 0, usage_before = 0; @@ -721,8 +731,8 @@ uint8_t Pager_object::handle_oom(addr_t transfer_from, /* retry upgrade using core quota if policy permits */ if (policy == UPGRADE_PREFER_SRC_TO_DST) { - if (transfer_from != __core_pd_sel) { - res = Nova::pd_ctrl(__core_pd_sel, Pd_op::TRANSFER_QUOTA, + if (transfer_from != core_pd_sel) { + res = Nova::pd_ctrl(core_pd_sel, Pd_op::TRANSFER_QUOTA, pd_sel(), QUOTA_TRANSFER_PAGES); if (res == Nova::NOVA_OK) return res; @@ -836,14 +846,14 @@ void Pager_object::_oom_handler(addr_t pager_dst, addr_t pager_src, utcb->set_msg_word(0); } - transfer_from = __core_pd_sel; + transfer_from = platform_specific()->core_pd_sel(); break; default: /* non core PD -> non core PD */ utcb->set_msg_word(0); if (pager_src == pager_dst || policy == UPGRADE_CORE_TO_DST) - transfer_from = __core_pd_sel; + transfer_from = platform_specific()->core_pd_sel(); else { /* delegation of items between different PDs */ src_pd = obj_src->client_pd(); @@ -877,12 +887,13 @@ addr_t Pager_object::get_oom_portal() addr_t const pt_oom = sel_oom_portal(); unsigned const genode_cpu_id = _location.xpos(); unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(genode_cpu_id); + addr_t const core_pd_sel = platform_specific()->core_pd_sel(); if (kernel_hip()->is_cpu_enabled(kernel_cpu_id) && pager_threads[genode_cpu_id]) { addr_t const ec_sel = pager_threads[genode_cpu_id]->native_thread().ec_sel; - uint8_t res = create_portal(pt_oom, __core_pd_sel, ec_sel, Mtd(0), + uint8_t res = create_portal(pt_oom, core_pd_sel, ec_sel, Mtd(0), reinterpret_cast(_oom_handler), this); if (res == Nova::NOVA_OK) diff --git a/repos/base-nova/src/core/platform.cc b/repos/base-nova/src/core/platform.cc index 5a90e19fce..1c6215db15 100644 --- a/repos/base-nova/src/core/platform.cc +++ b/repos/base-nova/src/core/platform.cc @@ -63,11 +63,6 @@ Utcb *__main_thread_utcb; */ extern unsigned _prog_img_beg, _prog_img_end; -/** - * Capability selector of root PD - */ -addr_t __core_pd_sel; - /** * Map preserved physical pages core-exclusive @@ -218,7 +213,7 @@ static void startup_handler() } -static void init_core_page_fault_handler() +static void init_core_page_fault_handler(addr_t const core_pd_sel) { /* create echo EC */ enum { @@ -228,20 +223,20 @@ static void init_core_page_fault_handler() addr_t ec_sel = cap_map()->insert(1); - uint8_t ret = create_ec(ec_sel, __core_pd_sel, boot_cpu(), + uint8_t ret = create_ec(ec_sel, core_pd_sel, boot_cpu(), CORE_PAGER_UTCB_ADDR, core_pager_stack_top(), EXC_BASE, GLOBAL); if (ret) log(__func__, ": create_ec returned ", ret); /* set up page-fault portal */ - create_pt(PT_SEL_PAGE_FAULT, __core_pd_sel, ec_sel, + create_pt(PT_SEL_PAGE_FAULT, core_pd_sel, ec_sel, Mtd(Mtd::QUAL | Mtd::ESP | Mtd::EIP), (addr_t)page_fault_handler); revoke(Obj_crd(PT_SEL_PAGE_FAULT, 0, Obj_crd::RIGHT_PT_CTRL)); /* startup portal for global core threads */ - create_pt(PT_SEL_STARTUP, __core_pd_sel, ec_sel, + create_pt(PT_SEL_STARTUP, core_pd_sel, ec_sel, Mtd(Mtd::EIP | Mtd::ESP), (addr_t)startup_handler); revoke(Obj_crd(PT_SEL_STARTUP, 0, Obj_crd::RIGHT_PT_CTRL)); @@ -291,10 +286,10 @@ Platform::Platform() : __main_thread_utcb = (Utcb *)(__initial_sp - get_page_size()); /* set core pd selector */ - __core_pd_sel = hip->sel_exc; + _core_pd_sel = hip->sel_exc; /* create lock used by capability allocator */ - Nova::create_sm(Nova::SM_SEL_EC, __core_pd_sel, 0); + Nova::create_sm(Nova::SM_SEL_EC, core_pd_sel(), 0); /* locally map the whole I/O port range */ enum { ORDER_64K = 16 }; @@ -380,7 +375,7 @@ Platform::Platform() : #endif /* set up page fault handler for core - for debugging */ - init_core_page_fault_handler(); + init_core_page_fault_handler(core_pd_sel()); if (verbose_boot_info) { if (hip->has_feature_vmx()) diff --git a/repos/base-nova/src/core/platform_thread.cc b/repos/base-nova/src/core/platform_thread.cc index 68f40b3888..fd99c41e3a 100644 --- a/repos/base-nova/src/core/platform_thread.cc +++ b/repos/base-nova/src/core/platform_thread.cc @@ -109,9 +109,8 @@ int Platform_thread::start(void *ip, void *sp) return -5; } - addr_t pd_core_sel = Platform_pd::pd_core_sel(); - addr_t pd_utcb = 0; - _sel_exc_base = vcpu() ? _pager->exc_pt_vcpu() : _pager->exc_pt_sel_client(); + addr_t pd_utcb = 0; + _sel_exc_base = vcpu() ? _pager->exc_pt_vcpu() : _pager->exc_pt_sel_client(); if (!vcpu()) { pd_utcb = stack_area_virtual_base() + stack_virtual_size() - get_page_size(); @@ -138,7 +137,8 @@ int Platform_thread::start(void *ip, void *sp) enum { KEEP_FREE_PAGES_NOT_AVAILABLE_FOR_UPGRADE = 2, UPPER_LIMIT_PAGES = 32 }; Obj_crd initial_pts(_sel_exc_base, pts, rights); - uint8_t res = create_pd(pd_sel, pd_core_sel, initial_pts, + uint8_t res = create_pd(pd_sel, platform_specific()->core_pd_sel(), + initial_pts, KEEP_FREE_PAGES_NOT_AVAILABLE_FOR_UPGRADE, UPPER_LIMIT_PAGES); if (res != NOVA_OK) { error("create_pd returned ", res); diff --git a/repos/base-nova/src/core/rpc_cap_factory.cc b/repos/base-nova/src/core/rpc_cap_factory.cc index 015491c75f..0abaedb99b 100644 --- a/repos/base-nova/src/core/rpc_cap_factory.cc +++ b/repos/base-nova/src/core/rpc_cap_factory.cc @@ -13,7 +13,7 @@ /* core-local includes */ #include -#include +#include /* NOVA includes */ #include @@ -23,9 +23,9 @@ using namespace Genode; Native_capability Rpc_cap_factory::alloc(Native_capability ep, addr_t entry, addr_t mtd) { - addr_t pt_sel = cap_map()->insert(); - addr_t pd_sel = Platform_pd::pd_core_sel(); - addr_t ec_sel = ep.local_name(); + addr_t const pt_sel = cap_map()->insert(); + addr_t const pd_sel = platform_specific()->core_pd_sel(); + addr_t const ec_sel = ep.local_name(); using namespace Nova; diff --git a/repos/base-nova/src/core/thread_start.cc b/repos/base-nova/src/core/thread_start.cc index 582be70d3e..bf3d57a477 100644 --- a/repos/base-nova/src/core/thread_start.cc +++ b/repos/base-nova/src/core/thread_start.cc @@ -26,7 +26,6 @@ /* core includes */ #include #include -#include using namespace Genode; @@ -43,7 +42,7 @@ void Thread::_init_platform_thread(size_t, Type type) if (type == MAIN) { /* set EC selector according to NOVA spec */ - native_thread().ec_sel = Platform_pd::pd_core_sel() + 1; + native_thread().ec_sel = platform_specific()->core_pd_sel() + 1; /* * Exception base of first thread in core is 0. We have to set @@ -56,11 +55,10 @@ void Thread::_init_platform_thread(size_t, Type type) } native_thread().ec_sel = cap_map()->insert(1); native_thread().exc_pt_sel = cap_map()->insert(NUM_INITIAL_PT_LOG2); - addr_t pd_sel = Platform_pd::pd_core_sel(); /* create running semaphore required for locking */ addr_t rs_sel =native_thread().exc_pt_sel + SM_SEL_EC; - uint8_t res = create_sm(rs_sel, pd_sel, 0); + uint8_t res = create_sm(rs_sel, platform_specific()->core_pd_sel(), 0); if (res != NOVA_OK) { error("create_sm returned ", res); throw Cpu_session::Thread_creation_failed(); @@ -94,7 +92,6 @@ void Thread::start() addr_t sp = _stack->top(); addr_t utcb = reinterpret_cast(&_stack->utcb()); Utcb * utcb_obj = reinterpret_cast(&_stack->utcb()); - addr_t pd_sel = Platform_pd::pd_core_sel(); Affinity::Location location = _affinity; @@ -104,7 +101,8 @@ void Thread::start() /* create local EC */ enum { LOCAL_THREAD = false }; unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(location.xpos()); - uint8_t res = create_ec(native_thread().ec_sel, pd_sel, kernel_cpu_id, + uint8_t res = create_ec(native_thread().ec_sel, + platform_specific()->core_pd_sel(), kernel_cpu_id, utcb, sp, native_thread().exc_pt_sel, LOCAL_THREAD); if (res != NOVA_OK) { error("create_ec returned ", res, " cpu=", location.xpos()); diff --git a/repos/base-nova/src/test/platform/main.cc b/repos/base-nova/src/test/platform/main.cc index 2b3848043e..0fbd1d8336 100644 --- a/repos/base-nova/src/test/platform/main.cc +++ b/repos/base-nova/src/test/platform/main.cc @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -580,42 +581,27 @@ class Greedy : public Genode::Thread { { log("starting"); - enum { SUB_RM_SIZE = 2UL * 1024 * 1024 * 1024 }; + enum { SUB_RM_SIZE = 1280 * 1024 * 1024 }; - Genode::Rm_connection rm(_env); - Genode::Region_map_client sub_rm(rm.create(SUB_RM_SIZE)); - addr_t const mem = _env.rm().attach(sub_rm.dataspace()); + Genode::Ram_dataspace_capability ds = _env.ram().alloc(4096); - Nova::Utcb * nova_utcb = reinterpret_cast(utcb()); Nova::Rights const mapping_rwx(true, true, true); - addr_t const page_fault_portal = native_thread().exc_pt_sel + 14; + log("cause mappings"); - log("cause mappings in range ", - Hex_range(mem, SUB_RM_SIZE), " ", &mem); + for (unsigned i = 0; i < SUB_RM_SIZE / 4096; i++) { - for (addr_t map_to = mem; map_to < mem + SUB_RM_SIZE; map_to += 4096) { - - /* setup faked page fault information */ - nova_utcb->items = ((addr_t)&nova_utcb->qual[2] - (addr_t)nova_utcb->msg) / sizeof(addr_t); - nova_utcb->ip = 0xbadaffe; - nova_utcb->qual[1] = (addr_t)&mem; - nova_utcb->crd_rcv = Nova::Mem_crd(map_to >> 12, 0, mapping_rwx); - - /* trigger faked page fault */ - Genode::uint8_t res = Nova::call(page_fault_portal); - if (res != Nova::NOVA_OK) { - log("call result=", res); - failed++; - return; - } + addr_t map_to = _env.rm().attach(ds); /* check that we really got the mapping */ touch_read(reinterpret_cast(map_to)); /* print status information in interval of 32M */ - if (!(map_to & (32UL * 1024 * 1024 - 1))) { - log(Hex(map_to)); + if (i % 8192 == 0) { + /* transfer some quota to avoid tons of upgrade messages */ + char const * const buf = "ram_quota=1280K"; + _env.parent().upgrade(_env.pd_session_cap(), buf); + log(Hex(i * 4096)); /* trigger some work to see quota in kernel decreasing */ // Nova::Rights rwx(true, true, true); // Nova::revoke(Nova::Mem_crd((map_to - 32 * 1024 * 1024) >> 12, 12, rwx)); diff --git a/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc b/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc index b69275639d..eb20d00e3e 100644 --- a/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc +++ b/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc @@ -83,15 +83,21 @@ static bool map_eager(Genode::addr_t const page, unsigned log2_order) addr_t const page_fault_portal = myself->native_thread().exc_pt_sel + 14; - /* setup faked page fault information */ - utcb->set_msg_word(((addr_t)&utcb->qual[2] - (addr_t)utcb->msg) / sizeof(addr_t)); - utcb->ip = reinterpret_cast(map_eager); - utcb->qual[1] = page; - utcb->crd_rcv = Nova::Mem_crd(page >> 12, log2_order - 12, mapping_rw); + while (true) { + /* setup faked page fault information */ + utcb->set_msg_word(((addr_t)&utcb->qual[2] - (addr_t)utcb->msg) / + sizeof(addr_t)); + utcb->ip = reinterpret_cast(map_eager); + utcb->qual[1] = page; + utcb->crd_rcv = Nova::Mem_crd(page >> 12, log2_order - 12, mapping_rw); - /* trigger faked page fault */ - Genode::uint8_t res = Nova::call(page_fault_portal); - return res == Nova::NOVA_OK; + /* trigger faked page fault */ + Genode::uint8_t res = Nova::call(page_fault_portal); + + bool const retry = utcb->msg_words(); + if (res != Nova::NOVA_OK || !retry) + return res == Nova::NOVA_OK; + }; } @@ -174,7 +180,7 @@ void Platform::Device_pd_component::assign_pci(Genode::Io_mem_dataspace_capabili "phys=", Genode::Hex(ds_client.phys_addr()), " " "virt=", Genode::Hex(page)); else - Genode::log("assignment of ", rid, " succeeded"); + Genode::log("assignment of PCI device ", Rid(rid), " succeeded"); /* we don't need the mapping anymore */ _address_space.detach(page);