diff --git a/base-codezero/src/core/include/platform_pd.h b/base-codezero/src/core/include/platform_pd.h index 9f4b39a1e..254823e39 100644 --- a/base-codezero/src/core/include/platform_pd.h +++ b/base-codezero/src/core/include/platform_pd.h @@ -16,6 +16,7 @@ /* core includes */ #include +#include /* Codezero includes */ #include @@ -23,7 +24,7 @@ namespace Genode { class Platform_thread; - class Platform_pd + class Platform_pd : public Address_space { private: @@ -37,7 +38,6 @@ namespace Genode { public: - /** * Constructors */ @@ -68,6 +68,13 @@ namespace Genode { * Assign parent interface to protection domain */ int assign_parent(Native_capability parent) { return 0; } + + + /***************************** + ** Address-space interface ** + *****************************/ + + void flush(addr_t, size_t) { PDBG("not implemented"); } }; } diff --git a/base-codezero/src/core/include/platform_thread.h b/base-codezero/src/core/include/platform_thread.h index 5eed8d62f..707bd0b6b 100644 --- a/base-codezero/src/core/include/platform_thread.h +++ b/base-codezero/src/core/include/platform_thread.h @@ -19,6 +19,9 @@ #include #include +/* core includes */ +#include + namespace Genode { class Platform_pd; @@ -30,19 +33,25 @@ namespace Genode { enum { PD_NAME_MAX_LEN = 64 }; - unsigned _tid; /* global codezero thread ID */ - unsigned _space_id; - addr_t _utcb; - char _name[PD_NAME_MAX_LEN]; - Pager_object *_pager; + unsigned _tid; /* global codezero thread ID */ + unsigned _space_id; + Weak_ptr _address_space; + addr_t _utcb; + char _name[PD_NAME_MAX_LEN]; + Pager_object *_pager; /** * Assign physical thread ID and UTCB address to thread * * This function is called from 'Platform_pd::bind_thread'. */ - void _assign_physical_thread(unsigned tid, unsigned space_id, addr_t utcb) { - _tid = tid; _space_id = space_id; _utcb = utcb; } + void _assign_physical_thread(unsigned tid, unsigned space_id, + addr_t utcb, + Weak_ptr address_space) + { + _tid = tid; _space_id = space_id; _utcb = utcb; + _address_space = address_space; + } public: @@ -100,6 +109,11 @@ namespace Genode { */ Thread_state state(); + /** + * Return the address space to which the thread is bound + */ + Weak_ptr address_space(); + /************************ ** Accessor functions ** diff --git a/base-codezero/src/core/platform_pd.cc b/base-codezero/src/core/platform_pd.cc index c2bb69831..23a8e5724 100644 --- a/base-codezero/src/core/platform_pd.cc +++ b/base-codezero/src/core/platform_pd.cc @@ -67,7 +67,8 @@ int Platform_pd::bind_thread(Platform_thread *thread) } addr_t utcb_addr = UTCB_VIRT_BASE + utcb_idx*sizeof(struct utcb); - thread->_assign_physical_thread(ids.tid, _space_id, utcb_addr); + thread->_assign_physical_thread(ids.tid, _space_id, utcb_addr, + this->Address_space::weak_ptr()); return 0; } diff --git a/base-codezero/src/core/platform_thread.cc b/base-codezero/src/core/platform_thread.cc index 3c4009214..cd77024e3 100644 --- a/base-codezero/src/core/platform_thread.cc +++ b/base-codezero/src/core/platform_thread.cc @@ -98,6 +98,12 @@ void Platform_thread::cancel_blocking() } +Weak_ptr Platform_thread::address_space() +{ + return _address_space; +} + + Platform_thread::Platform_thread(const char *name, unsigned, addr_t, int thread_id) : _tid(THREAD_INVALID) diff --git a/base-fiasco/src/core/include/platform_pd.h b/base-fiasco/src/core/include/platform_pd.h index 860da8eb8..12241b47f 100644 --- a/base-fiasco/src/core/include/platform_pd.h +++ b/base-fiasco/src/core/include/platform_pd.h @@ -18,6 +18,7 @@ #define _CORE__INCLUDE__PLATFORM_PD_H_ #include +#include namespace Fiasco { #include @@ -26,7 +27,7 @@ namespace Fiasco { namespace Genode { class Platform_thread; - class Platform_pd + class Platform_pd : public Address_space { private: @@ -176,6 +177,17 @@ namespace Genode { int assign_parent(Native_capability parent) { return 0; } int pd_id() const { return _pd_id; } + + + /***************************** + ** Address-space interface ** + *****************************/ + + /* + * On L4/Fiasco, we don't use directed unmap but rely on the + * in-kernel mapping database. See 'rm_session_support.cc'. + */ + void flush(addr_t, size_t) { PDBG("not implemented"); } }; } diff --git a/base-fiasco/src/core/include/platform_thread.h b/base-fiasco/src/core/include/platform_thread.h index 9a4cf9b61..90af57bdd 100644 --- a/base-fiasco/src/core/include/platform_thread.h +++ b/base-fiasco/src/core/include/platform_thread.h @@ -21,6 +21,7 @@ /* core includes */ #include +#include /* Fiasco includes */ namespace Fiasco { @@ -122,6 +123,11 @@ namespace Genode { */ void affinity(unsigned) { } + /** + * Return the address space to which the thread is bound + */ + Weak_ptr address_space(); + /************************ ** Accessor functions ** diff --git a/base-fiasco/src/core/platform_thread.cc b/base-fiasco/src/core/platform_thread.cc index 25a996c3d..a684469ab 100644 --- a/base-fiasco/src/core/platform_thread.cc +++ b/base-fiasco/src/core/platform_thread.cc @@ -145,6 +145,12 @@ void Platform_thread::cancel_blocking() } +Weak_ptr Platform_thread::address_space() +{ + return _platform_pd->Address_space::weak_ptr(); +} + + Platform_thread::Platform_thread(const char *name, unsigned, addr_t, int thread_id) : _thread_id(thread_id), _l4_thread_id(L4_INVALID_ID), _pager(0) { diff --git a/base-foc/src/core/include/platform_pd.h b/base-foc/src/core/include/platform_pd.h index c3e1a44f8..7426c7751 100644 --- a/base-foc/src/core/include/platform_pd.h +++ b/base-foc/src/core/include/platform_pd.h @@ -27,6 +27,7 @@ /* core includes */ #include +#include /* Fiasco.OC includes */ namespace Fiasco { @@ -36,7 +37,7 @@ namespace Fiasco { namespace Genode { class Platform_thread; - class Platform_pd + class Platform_pd : public Address_space { private: @@ -97,11 +98,23 @@ namespace Genode { */ int assign_parent(Native_capability parent); + /******************************* ** Fiasco-specific Accessors ** *******************************/ Native_capability native_task() { return _task.local; } + + + /***************************** + ** Address-space interface ** + *****************************/ + + /* + * On Fiasco.OC, we don't use directed unmap but rely on the + * in-kernel mapping database. See 'rm_session_support.cc'. + */ + void flush(addr_t, size_t) { PDBG("not implemented"); } }; } diff --git a/base-foc/src/core/include/platform_thread.h b/base-foc/src/core/include/platform_thread.h index 12d64f8db..aac52508e 100644 --- a/base-foc/src/core/include/platform_thread.h +++ b/base-foc/src/core/include/platform_thread.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace Genode { @@ -134,6 +135,11 @@ namespace Genode { */ void affinity(unsigned cpu); + /** + * Return the address space to which the thread is bound + */ + Weak_ptr address_space(); + /************************ ** Accessor functions ** diff --git a/base-foc/src/core/platform_thread.cc b/base-foc/src/core/platform_thread.cc index 451e2d5bf..5ca59200e 100644 --- a/base-foc/src/core/platform_thread.cc +++ b/base-foc/src/core/platform_thread.cc @@ -237,6 +237,12 @@ void Platform_thread::_finalize_construction(const char *name) } +Weak_ptr Platform_thread::address_space() +{ + return _platform_pd->Address_space::weak_ptr(); +} + + Platform_thread::Platform_thread(const char *name, unsigned prio) : _core_thread(false), diff --git a/base-host/src/core/include/platform_thread.h b/base-host/src/core/include/platform_thread.h index 114ee796a..921face7a 100644 --- a/base-host/src/core/include/platform_thread.h +++ b/base-host/src/core/include/platform_thread.h @@ -19,6 +19,9 @@ #include #include +/* core includes */ +#include + namespace Genode { class Platform_pd; @@ -80,6 +83,11 @@ namespace Genode { */ Thread_state state(); + /** + * Return the address space to which the thread is bound + */ + Weak_ptr address_space(); + /************************ ** Accessor functions ** diff --git a/base-host/src/core/platform_thread.cc b/base-host/src/core/platform_thread.cc index 1c1354ecf..e97874823 100644 --- a/base-host/src/core/platform_thread.cc +++ b/base-host/src/core/platform_thread.cc @@ -73,6 +73,13 @@ unsigned long Platform_thread::pager_object_badge() const } +Weak_ptr Platform_thread::address_space() +{ + PWRN("not implemented"); + return Weak_ptr(); +} + + Platform_thread::Platform_thread(const char *name, unsigned, addr_t, int thread_id) { diff --git a/base-hw/src/core/include/platform_pd.h b/base-hw/src/core/include/platform_pd.h index c79654eb3..1b16d5fd5 100644 --- a/base-hw/src/core/include/platform_pd.h +++ b/base-hw/src/core/include/platform_pd.h @@ -20,6 +20,7 @@ /* Core includes */ #include #include +#include namespace Kernel { @@ -34,7 +35,7 @@ namespace Genode /** * Platform specific part of a Genode protection domain */ - class Platform_pd + class Platform_pd : public Address_space { unsigned _id; /* ID of our kernel object */ Native_capability _parent; /* our parent interface */ @@ -77,9 +78,9 @@ namespace Genode { /* annotate that we've got a main thread from now on */ _main_thread = t->id(); - return t->join_pd(_id, 1); + return t->join_pd(_id, 1, Address_space::weak_ptr()); } - return t->join_pd(_id, 0); + return t->join_pd(_id, 0, Address_space::weak_ptr()); } /** @@ -98,6 +99,13 @@ namespace Genode _parent = parent; return 0; } + + + /***************************** + ** Address-space interface ** + *****************************/ + + void flush(addr_t, size_t) { PDBG("not implemented"); } }; } diff --git a/base-hw/src/core/include/platform_thread.h b/base-hw/src/core/include/platform_thread.h index 485fef4bf..76a795754 100644 --- a/base-hw/src/core/include/platform_thread.h +++ b/base-hw/src/core/include/platform_thread.h @@ -24,6 +24,7 @@ /* core includes */ #include +#include namespace Genode { @@ -43,6 +44,7 @@ namespace Genode { Thread_base * _thread_base; size_t _stack_size; unsigned _pd_id; + Weak_ptr _address_space; unsigned _id; Rm_client * _rm_client; bool _main_thread; @@ -91,7 +93,8 @@ namespace Genode { * \retval 0 on success * \retval <0 otherwise */ - int join_pd(unsigned const pd_id, bool const main_thread); + int join_pd(unsigned const pd_id, bool const main_thread, + Weak_ptr address_space); /** * Run this thread @@ -142,6 +145,11 @@ namespace Genode { void affinity(unsigned cpu) { kernel_log() << __PRETTY_FUNCTION__ << ": not implemented\n"; }; + /** + * Return the address space to which the thread is bound + */ + Weak_ptr address_space(); + /*************** ** Accessors ** diff --git a/base-hw/src/core/platform_thread.cc b/base-hw/src/core/platform_thread.cc index ec813fe01..b4e16a52d 100644 --- a/base-hw/src/core/platform_thread.cc +++ b/base-hw/src/core/platform_thread.cc @@ -32,6 +32,12 @@ bool Platform_thread::_attaches_utcb_by_itself() } +Weak_ptr Platform_thread::address_space() +{ + return _address_space; +} + + Platform_thread::~Platform_thread() { /* detach UTCB if main thread outside core */ @@ -102,14 +108,16 @@ Platform_thread::Platform_thread(const char * name, unsigned int priority, } -int Platform_thread::join_pd(unsigned const pd_id, bool const main_thread) +int Platform_thread::join_pd(unsigned const pd_id, bool const main_thread, + Weak_ptr address_space) { /* check if we're already in another PD */ if (_pd_id && _pd_id != pd_id) return -1; /* denote configuration for start method */ - _pd_id = pd_id; - _main_thread = main_thread; + _pd_id = pd_id; + _main_thread = main_thread; + _address_space = address_space; return 0; } diff --git a/base-nova/src/core/include/platform_pd.h b/base-nova/src/core/include/platform_pd.h index 6a8986cae..8841a146d 100644 --- a/base-nova/src/core/include/platform_pd.h +++ b/base-nova/src/core/include/platform_pd.h @@ -15,6 +15,7 @@ #define _CORE__INCLUDE__PLATFORM_PD_H_ #include +#include /* * Must be initialized by the startup code, @@ -25,7 +26,7 @@ extern Genode::addr_t __core_pd_sel; namespace Genode { class Platform_thread; - class Platform_pd + class Platform_pd : public Address_space { private: @@ -88,6 +89,17 @@ namespace Genode { * \return PD selector */ static addr_t pd_core_sel() { return __core_pd_sel; } + + + /***************************** + ** Address-space interface ** + *****************************/ + + /* + * On NOVA, we don't use directed unmap but rely on the + * in-kernel mapping database. See 'rm_session_support.cc'. + */ + void flush(addr_t, size_t) { PDBG("not implemented"); } }; } diff --git a/base-nova/src/core/include/platform_thread.h b/base-nova/src/core/include/platform_thread.h index a69aa9b11..9572bf737 100644 --- a/base-nova/src/core/include/platform_thread.h +++ b/base-nova/src/core/include/platform_thread.h @@ -22,6 +22,9 @@ #include #include +/* core includes */ +#include + namespace Genode { class Platform_pd; @@ -98,6 +101,11 @@ namespace Genode { */ Thread_state state(); + /** + * Return the address space to which the thread is bound + */ + Weak_ptr address_space(); + /************************ ** Accessor functions ** diff --git a/base-nova/src/core/platform_thread.cc b/base-nova/src/core/platform_thread.cc index a3d14af99..fdfeb5d4a 100644 --- a/base-nova/src/core/platform_thread.cc +++ b/base-nova/src/core/platform_thread.cc @@ -309,6 +309,12 @@ unsigned long Platform_thread::pager_object_badge() const } +Weak_ptr Platform_thread::address_space() +{ + return _pd->Address_space::weak_ptr(); +} + + Platform_thread::Platform_thread(const char *name, unsigned, int thread_id) : _pd(0), _pager(0), _id_base(cap_selector_allocator()->alloc(1)), diff --git a/base-okl4/src/core/include/platform_pd.h b/base-okl4/src/core/include/platform_pd.h index 66ac64782..9e7826614 100644 --- a/base-okl4/src/core/include/platform_pd.h +++ b/base-okl4/src/core/include/platform_pd.h @@ -14,7 +14,9 @@ #ifndef _CORE__INCLUDE__PLATFORM_PD_H_ #define _CORE__INCLUDE__PLATFORM_PD_H_ +/* core includes */ #include +#include namespace Okl4 { extern "C" { #include @@ -23,7 +25,7 @@ namespace Okl4 { extern "C" { namespace Genode { class Platform_thread; - class Platform_pd + class Platform_pd : public Address_space { private: @@ -185,6 +187,13 @@ namespace Genode { void space_pager(Platform_thread *pd); int pd_id() const { return _pd_id; } + + + /***************************** + ** Address-space interface ** + *****************************/ + + void flush(addr_t, size_t); }; } diff --git a/base-okl4/src/core/include/platform_thread.h b/base-okl4/src/core/include/platform_thread.h index c21cda1e8..44404cdbc 100644 --- a/base-okl4/src/core/include/platform_thread.h +++ b/base-okl4/src/core/include/platform_thread.h @@ -21,6 +21,7 @@ /* core includes */ #include +#include namespace Genode { @@ -110,6 +111,11 @@ namespace Genode { */ Thread_state state(); + /** + * Return the address space to which the thread is bound + */ + Weak_ptr address_space(); + /************************ ** Accessor functions ** diff --git a/base-okl4/src/core/platform_pd.cc b/base-okl4/src/core/platform_pd.cc index 387c50310..43ac47fef 100644 --- a/base-okl4/src/core/platform_pd.cc +++ b/base-okl4/src/core/platform_pd.cc @@ -257,6 +257,69 @@ void Platform_pd::_setup_address_space() } +static const bool verbose_unmap = false; + + +static void unmap_log2_range(unsigned pd_id, addr_t base, size_t size_log2) +{ + using namespace Okl4; + + L4_Fpage_t fpage = L4_FpageLog2(base, size_log2); + L4_FpageAddRightsTo(&fpage, L4_FullyAccessible); + int ret = L4_UnmapFpage(L4_SpaceId(pd_id), fpage); + if (ret != 1) + PERR("could not unmap page at %p from space %x (Error Code %ld)", + (void *)base, pd_id, L4_ErrorCode()); +} + + +void Platform_pd::flush(addr_t addr, size_t size) +{ + using namespace Okl4; + + L4_Word_t remaining_size = size; + L4_Word_t size_log2 = get_page_size_log2(); + + if (verbose_unmap) + printf("PD %d: unmap [%lx,%lx)\n", _pd_id, addr, addr + size); + + /* + * Let unmap granularity ('size_log2') grow + */ + while (remaining_size >= (1UL << size_log2)) { + + enum { SIZE_LOG2_MAX = 22 /* 4M */ }; + + /* issue 'unmap' for the current address if flexpage aligned */ + if (addr & (1 << size_log2)) { + unmap_log2_range(_pd_id, addr, size_log2); + + remaining_size -= 1 << size_log2; + addr += 1 << size_log2; + } + + /* increase flexpage size */ + size_log2++; + } + + /* + * Let unmap granularity ('size_log2') shrink + */ + while (remaining_size > 0) { + + if (remaining_size >= (1UL << size_log2)) { + unmap_log2_range(_pd_id, addr, size_log2); + + remaining_size -= 1 << size_log2; + addr += 1 << size_log2; + } + + /* decrease flexpage size */ + size_log2--; + } +} + + Platform_pd::Platform_pd(bool core) : _space_pager(0) { diff --git a/base-okl4/src/core/platform_thread.cc b/base-okl4/src/core/platform_thread.cc index 36aaa9f21..b88e74475 100644 --- a/base-okl4/src/core/platform_thread.cc +++ b/base-okl4/src/core/platform_thread.cc @@ -178,6 +178,12 @@ unsigned long Platform_thread::pager_object_badge() const } +Weak_ptr Platform_thread::address_space() +{ + return _platform_pd->Address_space::weak_ptr(); +} + + Platform_thread::Platform_thread(const char *name, unsigned prio, addr_t, int thread_id) : _thread_id(thread_id), _l4_thread_id(L4_nilthread), _platform_pd(0), _priority(prio), _pager(0) diff --git a/base-okl4/src/core/rm_session_support.cc b/base-okl4/src/core/rm_session_support.cc index 8f8858458..49fddeb1a 100644 --- a/base-okl4/src/core/rm_session_support.cc +++ b/base-okl4/src/core/rm_session_support.cc @@ -17,74 +17,13 @@ /* core includes */ #include -/* OKL4 includes */ -namespace Okl4 { extern "C" { -#include -#include -#include -} } - using namespace Genode; -using namespace Okl4; - -static const bool verbose_unmap = false; - - -static void unmap_log2_range(L4_SpaceId_t space_id, L4_Word_t base, L4_Word_t size_log2) -{ - L4_Fpage_t fpage = L4_FpageLog2(base, size_log2); - L4_FpageAddRightsTo(&fpage, L4_FullyAccessible); - int ret = L4_UnmapFpage(space_id, fpage); - if (ret != 1) - PERR("could not unmap page at %p from space %lx (Error Code %ld)", - (void *)base, space_id.raw, L4_ErrorCode()); -} void Rm_client::unmap(addr_t, addr_t virt_base, size_t size) { - L4_ThreadId_t tid = { raw : badge() }; - L4_SpaceId_t space_id = { raw: L4_ThreadNo(tid) >> Thread_id_bits::THREAD }; - L4_Word_t addr = virt_base; - L4_Word_t remaining_size = size; - L4_Word_t size_log2 = get_page_size_log2(); + Locked_ptr locked_address_space(_address_space); - if (verbose_unmap) - printf("RM client %p (%lx) unmap [%lx,%lx)\n", - this, badge(), virt_base, virt_base + size); - - /* - * Let unmap granularity ('size_log2') grow - */ - while (remaining_size >= (1UL << size_log2)) { - - enum { SIZE_LOG2_MAX = 22 /* 4M */ }; - - /* issue 'unmap' for the current address if flexpage aligned */ - if (addr & (1 << size_log2)) { - unmap_log2_range(space_id, addr, size_log2); - - remaining_size -= 1 << size_log2; - addr += 1 << size_log2; - } - - /* increase flexpage size */ - size_log2++; - } - - /* - * Let unmap granularity ('size_log2') shrink - */ - while (remaining_size > 0) { - - if (remaining_size >= (1UL << size_log2)) { - unmap_log2_range(space_id, addr, size_log2); - - remaining_size -= 1 << size_log2; - addr += 1 << size_log2; - } - - /* decrease flexpage size */ - size_log2--; - } + if (locked_address_space.is_valid()) + locked_address_space->flush(virt_base, size); } diff --git a/base-pistachio/src/core/include/platform_pd.h b/base-pistachio/src/core/include/platform_pd.h index 3a7b01ba7..986501ab2 100644 --- a/base-pistachio/src/core/include/platform_pd.h +++ b/base-pistachio/src/core/include/platform_pd.h @@ -15,6 +15,7 @@ #define _CORE__INCLUDE__PLATFORM_PD_H_ #include +#include namespace Pistachio { #include @@ -23,7 +24,7 @@ namespace Pistachio { namespace Genode { class Platform_thread; - class Platform_pd + class Platform_pd : public Address_space { private: @@ -216,6 +217,17 @@ namespace Genode { int assign_parent(Native_capability parent) { return 0; } int pd_id() const { return _pd_id; } + + + /***************************** + ** Address-space interface ** + *****************************/ + + /* + * On Pistachio, we don't use directed unmap but rely on the + * in-kernel mapping database. See 'rm_session_support.cc'. + */ + void flush(addr_t, size_t) { PDBG("not implemented"); } }; } diff --git a/base-pistachio/src/core/include/platform_thread.h b/base-pistachio/src/core/include/platform_thread.h index 14296132d..c47a06044 100644 --- a/base-pistachio/src/core/include/platform_thread.h +++ b/base-pistachio/src/core/include/platform_thread.h @@ -21,6 +21,7 @@ /* core includes */ #include +#include /* Pistachio includes */ namespace Pistachio { @@ -114,6 +115,11 @@ namespace Genode { */ Thread_state state(); + /** + * Return the address space to which the thread is bound + */ + Weak_ptr address_space(); + /************************ ** Accessor functions ** diff --git a/base-pistachio/src/core/platform_thread.cc b/base-pistachio/src/core/platform_thread.cc index 9fd5ac264..5c71107e1 100644 --- a/base-pistachio/src/core/platform_thread.cc +++ b/base-pistachio/src/core/platform_thread.cc @@ -226,6 +226,12 @@ void Platform_thread::cancel_blocking() } +Weak_ptr Platform_thread::address_space() +{ + return _platform_pd->Address_space::weak_ptr(); +} + + Platform_thread::Platform_thread(const char *name, unsigned prio, addr_t, int id) : _thread_id(id), _l4_thread_id(L4_nilthread), _priority(prio), _pager(0) { diff --git a/base/include/rm_session/rm_session.h b/base/include/rm_session/rm_session.h index 4709812bc..1142c0995 100644 --- a/base/include/rm_session/rm_session.h +++ b/base/include/rm_session/rm_session.h @@ -100,6 +100,7 @@ namespace Genode { class Out_of_metadata : public Attach_failed { }; class Invalid_thread : public Exception { }; + class Unbound_thread : public Exception { }; /** * Destructor @@ -156,6 +157,7 @@ namespace Genode { * \param thread thread that will be paged * \throw Invalid_thread * \throw Out_of_metadata + * \throw Unbound_thread * \return capability to be used for handling page faults * * This method must be called at least once to establish a valid diff --git a/base/src/core/include/address_space.h b/base/src/core/include/address_space.h new file mode 100644 index 000000000..6fe53efcc --- /dev/null +++ b/base/src/core/include/address_space.h @@ -0,0 +1,33 @@ +/* + * \brief Interface for flushing mapping from a protection domain + * \author Norman Feske + * \date 2013-03-07 + */ + +/* + * Copyright (C) 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. + */ + +#ifndef _CORE__INCLUDE__ADDRESS_SPACE_H_ +#define _CORE__INCLUDE__ADDRESS_SPACE_H_ + +#include +#include + +namespace Genode { struct Address_space; } + +struct Genode::Address_space : Genode::Volatile_object +{ + /** + * Flush memory mappings of virtual address range + * + * \param virt_addr start address of range to flush + * \param size size of range in bytes, must be a multiple of page size + */ + virtual void flush(addr_t virt_addr, size_t size) = 0; +}; + +#endif /* _CORE__INCLUDE__ADDRESS_SPACE_H_ */ diff --git a/base/src/core/include/rm_session_component.h b/base/src/core/include/rm_session_component.h index 9cacd833b..c54c358ab 100644 --- a/base/src/core/include/rm_session_component.h +++ b/base/src/core/include/rm_session_component.h @@ -32,10 +32,10 @@ #include #include #include +#include namespace Genode { - class Dataspace_component; class Rm_session_component; class Rm_client; @@ -185,6 +185,10 @@ namespace Genode { class Rm_client : public Pager_object, public Rm_member, public Rm_faulter, public List::Element { + private: + + Weak_ptr _address_space; + public: /** @@ -194,8 +198,11 @@ namespace Genode { * \param badge pager-object badge used of identifying the client * when a page-fault occurs */ - Rm_client(Rm_session_component *session, unsigned long badge) : - Pager_object(badge), Rm_member(session), Rm_faulter(this) { } + Rm_client(Rm_session_component *session, unsigned long badge, + Weak_ptr &address_space) + : + Pager_object(badge), Rm_member(session), Rm_faulter(this), + _address_space(address_space) { } int pager(Ipc_pager &pager); @@ -203,6 +210,11 @@ namespace Genode { * Flush memory mappings for the specified virtual address range */ void unmap(addr_t core_local_base, addr_t virt_base, size_t size); + + bool has_same_address_space(Rm_client const &other) + { + return other._address_space == _address_space; + } }; diff --git a/base/src/core/rm_session_component.cc b/base/src/core/rm_session_component.cc index 63f0bed07..5bc5d1c2c 100644 --- a/base/src/core/rm_session_component.cc +++ b/base/src/core/rm_session_component.cc @@ -545,7 +545,9 @@ void Rm_session_component::detach(Local_addr local_addr) * Go through all RM clients using the RM session. For each RM client, we * need to unmap the referred region from its virtual address space. */ - for (Rm_client *rc = _clients.first(); rc; rc = rc->List::Element::next()) { + Rm_client *prev_rc = 0; + Rm_client *rc = _clients.first(); + for (; rc; rc = rc->List::Element::next(), prev_rc = rc) { /* * XXX Unmapping managed dataspaces on kernels, which take a core- @@ -563,6 +565,23 @@ void Rm_session_component::detach(Local_addr local_addr) break; } + /* + * Don't unmap from the same address space twice. If multiple threads + * reside in one PD, each thread will have a corresponding 'Rm_client' + * object. Consequenlty, an unmap operation referring to the PD is + * issued multiple times, one time for each thread. By comparing the + * membership to the thread's respective address spaces, we reduce + * superfluous unmap operations. + * + * Note that the list of 'Rm_client' object may contain threads of + * different address spaces in any order. So superfluous unmap + * operations can still happen if 'Rm_client' objects of one PD are + * interleaved with 'Rm_client' objects of another PD. In practice, + * however, this corner case is rare. + */ + if (prev_rc && prev_rc->has_same_address_space(*rc)) + continue; + rc->unmap(dsc->core_local_addr() + region->offset(), region->base(), region->size()); } @@ -588,6 +607,7 @@ void Rm_session_component::detach(Local_addr local_addr) Pager_capability Rm_session_component::add_client(Thread_capability thread) { unsigned long badge; + Weak_ptr address_space; { /* lookup thread and setup correct parameters */ @@ -597,13 +617,17 @@ Pager_capability Rm_session_component::add_client(Thread_capability thread) /* determine identification of client when faulting */ badge = cpu_thread->platform_thread()->pager_object_badge(); + + address_space = cpu_thread->platform_thread()->address_space(); + if (!Locked_ptr(address_space).is_valid()) + throw Unbound_thread(); } /* serialize access */ Lock::Guard lock_guard(_lock); Rm_client *cl; - try { cl = new(&_client_slab) Rm_client(this, badge); } + try { cl = new(&_client_slab) Rm_client(this, badge, address_space); } catch (Allocator::Out_of_memory) { throw Out_of_metadata(); } catch (Cpu_session::Thread_creation_failed) { throw Out_of_metadata(); } catch (Thread_base::Stack_alloc_failed) { throw Out_of_metadata(); }