diff --git a/repos/base-fiasco/src/core/target.inc b/repos/base-fiasco/src/core/target.inc
index 3c588bbbe6..72b747854e 100644
--- a/repos/base-fiasco/src/core/target.inc
+++ b/repos/base-fiasco/src/core/target.inc
@@ -19,6 +19,8 @@ SRC_CC      += cap_session_component.cc \
                pager_ep.cc \
                pager_object.cc \
                pd_session_component.cc \
+               pd_assign_pci.cc \
+               pd_upgrade_ram_quota.cc \
                platform.cc \
                platform_pd.cc \
                platform_services.cc \
@@ -28,7 +30,6 @@ SRC_CC      += cap_session_component.cc \
                rm_session_component.cc \
                rm_session_support.cc \
                rom_session_component.cc \
-               signal_session_component.cc \
                signal_source_component.cc \
                thread_start.cc \
                trace_session_component.cc
@@ -49,10 +50,11 @@ vpath rom_session_component.cc    $(GEN_CORE_DIR)
 vpath cap_session_component.cc    $(GEN_CORE_DIR)
 vpath cpu_session_component.cc    $(GEN_CORE_DIR)
 vpath pd_session_component.cc     $(GEN_CORE_DIR)
+vpath pd_assign_pci.cc            $(GEN_CORE_DIR)
+vpath pd_upgrade_ram_quota.cc     $(GEN_CORE_DIR)
 vpath rm_session_component.cc     $(GEN_CORE_DIR)
 vpath io_mem_session_component.cc $(GEN_CORE_DIR)
 vpath io_mem_session_support.cc   $(GEN_CORE_DIR)
-vpath signal_session_component.cc $(GEN_CORE_DIR)
 vpath signal_source_component.cc  $(GEN_CORE_DIR)
 vpath trace_session_component.cc  $(GEN_CORE_DIR)
 vpath dataspace_component.cc      $(GEN_CORE_DIR)
diff --git a/repos/base-foc/include/signal_session/foc_source.h b/repos/base-foc/include/signal_session/foc_source.h
deleted file mode 100644
index 267d33b8cb..0000000000
--- a/repos/base-foc/include/signal_session/foc_source.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * \brief  Fiasco.OC-specific signal source RPC interface
- * \author Norman Feske
- * \author Stefan Kalkowski
- * \date   2011-04-12
- */
-
-/*
- * Copyright (C) 2011-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 _INCLUDE__SIGNAL_SESSION__FOC_SOURCE_H_
-#define _INCLUDE__SIGNAL_SESSION__FOC_SOURCE_H_
-
-#include <base/rpc.h>
-#include <signal_session/source.h>
-
-namespace Genode {
-
-	struct Foc_signal_source : Signal_source
-	{
-		/*********************
-		 ** RPC declaration **
-		 *********************/
-
-		GENODE_RPC(Rpc_request_semaphore, Native_capability, _request_semaphore);
-
-		GENODE_RPC_INTERFACE_INHERIT(Signal_source, Rpc_request_semaphore);
-	};
-}
-
-#endif /* _INCLUDE__SIGNAL_SESSION__FOC_SOURCE_H_ */
diff --git a/repos/base-foc/include/signal_session/source_rpc_object.h b/repos/base-foc/include/signal_session/source_rpc_object.h
deleted file mode 100644
index 15741ed24b..0000000000
--- a/repos/base-foc/include/signal_session/source_rpc_object.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * \brief  Signal-source server interface
- * \author Norman Feske
- * \date   2010-02-03
- */
-
-/*
- * 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.
- */
-
-#ifndef _INCLUDE__SIGNAL_SESSION__SOURCE_RPC_OBJECT_H_
-#define _INCLUDE__SIGNAL_SESSION__SOURCE_RPC_OBJECT_H_
-
-#include <base/rpc_server.h>
-#include <signal_session/foc_source.h>
-
-namespace Genode {
-
-	struct Signal_source_rpc_object : Rpc_object<Foc_signal_source, Signal_source_rpc_object>
-	{
-		protected:
-
-			Native_capability _blocking_semaphore;
-
-		public:
-
-			Signal_source_rpc_object(Native_capability cap)
-			: _blocking_semaphore(cap) {}
-
-			Native_capability _request_semaphore() { return _blocking_semaphore; }
-	};
-}
-
-#endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_RPC_OBJECT_H_ */
diff --git a/repos/base-foc/include/signal_session/source_client.h b/repos/base-foc/include/signal_source/client.h
similarity index 90%
rename from repos/base-foc/include/signal_session/source_client.h
rename to repos/base-foc/include/signal_source/client.h
index ae87b670ce..b5f65f598e 100644
--- a/repos/base-foc/include/signal_session/source_client.h
+++ b/repos/base-foc/include/signal_source/client.h
@@ -20,12 +20,12 @@
  * under the terms of the GNU General Public License version 2.
  */
 
-#ifndef _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_
-#define _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_
+#ifndef _INCLUDE__SIGNAL_SOURCE__CLIENT_H_
+#define _INCLUDE__SIGNAL_SOURCE__CLIENT_H_
 
 #include <base/rpc_client.h>
 #include <base/thread.h>
-#include <signal_session/foc_source.h>
+#include <signal_source/foc_signal_source.h>
 
 namespace Fiasco {
 #include <l4/sys/irq.h>
@@ -63,7 +63,7 @@ namespace Genode {
 			/**
 			 * Constructor
 			 */
-			Signal_source_client(Signal_source_capability cap)
+			Signal_source_client(Capability<Signal_source> cap)
 			: Rpc_client<Foc_signal_source>(static_cap_cast<Foc_signal_source>(cap))
 			{ _init_sem(); }
 
@@ -92,4 +92,4 @@ namespace Genode {
 	};
 }
 
-#endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_ */
+#endif /* _INCLUDE__SIGNAL_SOURCE__CLIENT_H_ */
diff --git a/repos/base-foc/include/signal_source/foc_signal_source.h b/repos/base-foc/include/signal_source/foc_signal_source.h
new file mode 100644
index 0000000000..1d66b8fac4
--- /dev/null
+++ b/repos/base-foc/include/signal_source/foc_signal_source.h
@@ -0,0 +1,30 @@
+/*
+ * \brief  Fiasco.OC-specific signal source RPC interface
+ * \author Norman Feske
+ * \author Stefan Kalkowski
+ * \date   2011-04-12
+ */
+
+/*
+ * Copyright (C) 2011-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 _INCLUDE__SIGNAL_SOURCE__FOC_SIGNAL_SOURCE_H_
+#define _INCLUDE__SIGNAL_SOURCE__FOC_SIGNAL_SOURCE_H_
+
+#include <signal_source/signal_source.h>
+#include <base/rpc_server.h>
+
+namespace Genode { struct Foc_signal_source; }
+
+
+struct Genode::Foc_signal_source : Signal_source
+{
+	GENODE_RPC(Rpc_request_semaphore, Native_capability, _request_semaphore);
+	GENODE_RPC_INTERFACE_INHERIT(Signal_source, Rpc_request_semaphore);
+};
+
+#endif /* _INCLUDE__SIGNAL_SOURCE__SIGNAL_SOURCE_H_ */
diff --git a/repos/base-foc/include/signal_source/rpc_object.h b/repos/base-foc/include/signal_source/rpc_object.h
new file mode 100644
index 0000000000..3afd8a56a8
--- /dev/null
+++ b/repos/base-foc/include/signal_source/rpc_object.h
@@ -0,0 +1,38 @@
+/*
+ * \brief  Signal-source server interface
+ * \author Norman Feske
+ * \date   2010-02-03
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _INCLUDE__SIGNAL_SOURCE__RPC_OBJECT_H_
+#define _INCLUDE__SIGNAL_SOURCE__RPC_OBJECT_H_
+
+#include <base/rpc_server.h>
+#include <signal_source/foc_signal_source.h>
+
+namespace Genode { struct Signal_source_rpc_object; }
+
+
+struct Genode::Signal_source_rpc_object : Rpc_object<Foc_signal_source,
+                                                     Signal_source_rpc_object>
+{
+	protected:
+
+		Native_capability _blocking_semaphore;
+
+	public:
+
+		Signal_source_rpc_object(Native_capability cap)
+		: _blocking_semaphore(cap) {}
+
+		Native_capability _request_semaphore() { return _blocking_semaphore; }
+};
+
+#endif /* _INCLUDE__SIGNAL_SOURCE__RPC_OBJECT_H_ */
diff --git a/repos/base-foc/src/core/include/pd_session_component.h b/repos/base-foc/src/core/include/pd_session_component.h
index 0fbafaf27e..63c0d0b7c1 100644
--- a/repos/base-foc/src/core/include/pd_session_component.h
+++ b/repos/base-foc/src/core/include/pd_session_component.h
@@ -16,48 +16,90 @@
 #define _CORE__INCLUDE__PD_SESSION_COMPONENT_H_
 
 /* Genode includes */
+#include <util/arg_string.h>
 #include <foc_pd_session/foc_pd_session.h>
 #include <base/rpc_server.h>
 
 /* core includes */
 #include <platform_pd.h>
+#include <signal_broker.h>
 
-namespace Genode {
-
-	class Pd_session_component : public Rpc_object<Foc_pd_session>
-	{
-		private:
-
-			Platform_pd        _pd;
-			Parent_capability  _parent;
-			Rpc_entrypoint    *_thread_ep;
-
-		public:
-
-			Pd_session_component(Rpc_entrypoint *thread_ep,
-			                     Allocator *md_alloc, const char *args)
-			: _thread_ep(thread_ep) { }
-
-			/**
-			 * Register quota donation at allocator guard
-			 */
-			void upgrade_ram_quota(size_t ram_quota) { }
+namespace Genode { class Pd_session_component; }
 
 
-			/**************************
-			 ** PD session interface **
-			 **************************/
+class Genode::Pd_session_component : public Rpc_object<Foc_pd_session>
+{
+	private:
 
-			int bind_thread(Thread_capability);
-			int assign_parent(Parent_capability);
+		Allocator_guard    _md_alloc;   /* guarded meta-data allocator */
+		Platform_pd        _pd;
+		Capability<Parent> _parent;
+		Rpc_entrypoint    &_thread_ep;
+		Signal_broker      _signal_broker;
+
+		size_t _ram_quota(char const * args) {
+			return Arg_string::find_arg(args, "ram_quota").long_value(0); }
+
+	public:
+
+		Pd_session_component(Rpc_entrypoint &thread_ep,
+		                     Rpc_entrypoint &receiver_ep,
+		                     Rpc_entrypoint &context_ep,
+		                     Allocator      &md_alloc,
+		                     char const     *args)
+		:
+			_md_alloc(&md_alloc, _ram_quota(args)),
+			_thread_ep(thread_ep),
+			_signal_broker(_md_alloc, receiver_ep, context_ep)
+		{ }
+
+		/**
+		 * Register quota donation at allocator guard
+		 */
+		void upgrade_ram_quota(size_t ram_quota) {
+			_md_alloc.upgrade(ram_quota); }
 
 
-			/**********************************
-			 ** Fiasco.OC specific functions **
-			 **********************************/
+		/**************************
+		 ** PD session interface **
+		 **************************/
 
-			Native_capability task_cap();
-	};
-}
+		int bind_thread(Thread_capability) override;
+
+		int assign_parent(Capability<Parent>) override;
+
+		bool assign_pci(addr_t, uint16_t) override
+		{
+			PWRN("not implemented"); return false;
+		};
+
+		Signal_source_capability alloc_signal_source() override {
+			return _signal_broker.alloc_signal_source(); }
+
+		void free_signal_source(Signal_source_capability sig_rec_cap) override {
+			_signal_broker.free_signal_source(sig_rec_cap); }
+
+		Signal_context_capability
+		alloc_context(Signal_source_capability sig_rec_cap, unsigned long imprint) override
+		{
+			try {
+				return _signal_broker.alloc_context(sig_rec_cap, imprint); }
+			catch (Genode::Allocator::Out_of_memory) {
+				throw Pd_session::Out_of_metadata(); }
+		}
+
+		void free_context(Signal_context_capability cap) override {
+			_signal_broker.free_context(cap); }
+
+		void submit(Signal_context_capability cap, unsigned n) override {
+			_signal_broker.submit(cap, n); }
+
+
+		/**********************************
+		 ** Fiasco.OC specific functions **
+		 **********************************/
+
+		Native_capability task_cap();
+};
 
 #endif /* _CORE__INCLUDE__PD_SESSION_COMPONENT_H_ */
diff --git a/repos/base-foc/src/core/signal_source_component.cc b/repos/base-foc/src/core/signal_source_component.cc
index 29fb7cd880..fec106e41f 100644
--- a/repos/base-foc/src/core/signal_source_component.cc
+++ b/repos/base-foc/src/core/signal_source_component.cc
@@ -17,8 +17,8 @@
 #include <base/native_types.h>
 
 /* core includes */
-#include <signal_session_component.h>
 #include <platform.h>
+#include <signal_source_component.h>
 
 namespace Fiasco {
 #include <l4/sys/factory.h>
@@ -39,8 +39,7 @@ void Signal_source_component::release(Signal_context_component *context)
 }
 
 void Signal_source_component::submit(Signal_context_component *context,
-                                     Ipc_ostream              *ostream,
-                                     int                       cnt)
+                                     unsigned long             cnt)
 {
 	/* enqueue signal to context */
 	context->increment_signal_cnt(cnt);
diff --git a/repos/base-foc/src/core/target.inc b/repos/base-foc/src/core/target.inc
index 78a79f0372..89315c8406 100644
--- a/repos/base-foc/src/core/target.inc
+++ b/repos/base-foc/src/core/target.inc
@@ -31,7 +31,6 @@ SRC_CC      += cap_session_component.cc \
                rm_session_component.cc \
                rm_session_support.cc \
                rom_session_component.cc \
-               signal_session_component.cc \
                signal_source_component.cc \
                thread_start.cc \
                trace_session_component.cc
@@ -57,7 +56,6 @@ vpath pd_session_component.cc     $(GEN_CORE_DIR)
 vpath ram_session_component.cc    $(GEN_CORE_DIR)
 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_object.cc             $(GEN_CORE_DIR)
 vpath core_printf.cc              $(BASE_DIR)/src/base/console
diff --git a/repos/base-hw/include/pd_session/connection.h b/repos/base-hw/include/pd_session/connection.h
index baa96b9c87..297ab95217 100644
--- a/repos/base-hw/include/pd_session/connection.h
+++ b/repos/base-hw/include/pd_session/connection.h
@@ -26,7 +26,7 @@ namespace Genode { struct Pd_connection; }
 
 struct Genode::Pd_connection : Connection<Pd_session>, Pd_session_client
 {
-	enum { RAM_QUOTA = 20*1024 };
+	enum { RAM_QUOTA = 28*1024 };
 
 	/**
 	 * Constructor
diff --git a/repos/base-hw/include/signal_session/client.h b/repos/base-hw/include/signal_session/client.h
deleted file mode 100644
index 3cdc55eb10..0000000000
--- a/repos/base-hw/include/signal_session/client.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * \brief  Client-side implementation of the signal session interface
- * \author Martin Stein
- * \date   2012-05-05
- */
-
-/*
- * Copyright (C) 2012-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 _INCLUDE__SIGNAL_SESSION__CLIENT_H_
-#define _INCLUDE__SIGNAL_SESSION__CLIENT_H_
-
-/* Genode includes */
-#include <signal_session/capability.h>
-#include <signal_session/signal_session.h>
-#include <base/rpc_client.h>
-
-namespace Genode
-{
-	/**
- 	 * Client-side implementation of the signal session interface
-	 */
-	struct Signal_session_client : Rpc_client<Signal_session>
-	{
-		/**
-		 * Constructor
-		 *
-		 * \param s  targeted signal session
-		 */
-		explicit Signal_session_client(Signal_session_capability const s)
-		: Rpc_client<Signal_session>(s) { }
-
-		/******************************
-		 ** Signal_session interface **
-		 ******************************/
-
-		Signal_receiver_capability alloc_receiver()
-		{ return call<Rpc_alloc_receiver>(); }
-
-		Signal_context_capability
-		alloc_context(Signal_receiver_capability const r,
-		              unsigned const imprint) {
-			return call<Rpc_alloc_context>(r, imprint); }
-
-		void free_receiver(Signal_receiver_capability cap) {
-			call<Rpc_free_receiver>(cap); }
-
-		void free_context(Signal_context_capability cap) {
-			call<Rpc_free_context>(cap); }
-	};
-}
-
-#endif /* _INCLUDE__SIGNAL_SESSION__CLIENT_H_ */
diff --git a/repos/base-hw/include/signal_session/connection.h b/repos/base-hw/include/signal_session/connection.h
deleted file mode 100644
index 1b6abb51d2..0000000000
--- a/repos/base-hw/include/signal_session/connection.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * \brief  Connection to signal service
- * \author Stefan Kalkowski
- * \author Norman Feske
- * \date   2015-05-20
- *
- * This is a shadow copy of the generic header in base,
- * due to higher memory donation requirements in base-hw
- */
-
-/*
- * Copyright (C) 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.
- */
-
-#ifndef _INCLUDE__SIGNAL_SESSION__CONNECTION_H_
-#define _INCLUDE__SIGNAL_SESSION__CONNECTION_H_
-
-#include <signal_session/client.h>
-#include <base/connection.h>
-
-namespace Genode { struct Signal_connection; }
-
-
-struct Genode::Signal_connection : Connection<Signal_session>,
-                                   Signal_session_client
-{
-	Signal_connection()
-	: Connection<Signal_session>(session("ram_quota=32K")),
-	  Signal_session_client(cap()) { }
-};
-
-#endif /* _INCLUDE__CAP_SESSION__CONNECTION_H_ */
diff --git a/repos/base-hw/include/signal_session/signal_session.h b/repos/base-hw/include/signal_session/signal_session.h
deleted file mode 100644
index d168b63b31..0000000000
--- a/repos/base-hw/include/signal_session/signal_session.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * \brief  Signal session interface
- * \author Martin Stein
- * \date   2012-05-05
- */
-
-/*
- * Copyright (C) 2012-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 _INCLUDE__SIGNAL_SESSION__SIGNAL_SESSION_H_
-#define _INCLUDE__SIGNAL_SESSION__SIGNAL_SESSION_H_
-
-/* Genode includes */
-#include <base/capability.h>
-#include <base/exception.h>
-#include <session/session.h>
-
-namespace Genode
-{
-	class Signal_receiver;
-	class Signal_context;
-
-	/*
-	 * The 'dst' of this cap is used to communicate the ID of the
-	 * corresponding signal-receiver kernel-object or 0 if the cap is invalid.
-	 */
-	typedef Capability<Signal_receiver> Signal_receiver_capability;
-
-	/*
-	 * The 'dst' of this cap is used to communicate the ID of the
-	 * corresponding signal-context kernel-object or 0 if the cap is invalid.
-	 */
-	typedef Capability<Signal_context> Signal_context_capability;
-
-	/**
-	 * Signal session interface
-	 */
-	struct Signal_session : Session
-	{
-		class Out_of_metadata        : public Exception { };
-		class Create_receiver_failed : public Exception { };
-		class Create_context_failed  : public Exception { };
-		class Kill_receiver_failed   : public Exception { };
-		class Kill_context_failed    : public Exception { };
-
-		/**
-		 * String that can be used to refer to this service
-		 */
-		static const char * service_name() { return "SIGNAL"; }
-
-		/**
-		 * Destructor
-		 *
-		 * \throw Kill_context_failed
-		 * \throw Kill_receiver_failed
-		 */
-		virtual ~Signal_session() { }
-
-		/**
-		 * Create and manage a new signal receiver
-		 *
-		 * \return  a cap that acts as reference to the created object
-		 *
-		 * \throw Out_of_metadata
-		 * \throw Create_receiver_failed
-		 */
-		virtual Signal_receiver_capability alloc_receiver() = 0;
-
-		/**
-		 * Create and manage a new signal context
-		 *
-		 * \param r        names the signal receiver that shall provide
-		 *                 the new context
-		 * \param imprint  every signal that occures on the new context gets
-		 *                 signed with this value
-		 *
-		 * \return  a cap that acts as reference to the created object
-		 *
-		 * \throw Out_of_metadata
-		 * \throw Create_context_failed
-		 */
-		virtual Signal_context_capability
-		alloc_context(Signal_receiver_capability r,
-		              unsigned const imprint) = 0;
-
-		/**
-		 * Free a signal receiver
-		 *
-		 * \param cap  capability of targeted signal receiver
-		 *
-		 * \throw Kill_receiver_failed
-		 */
-		virtual void free_receiver(Signal_receiver_capability cap) = 0;
-
-		/**
-		 * Free a signal context
-		 *
-		 * \param cap  capability of targeted signal context
-		 *
-		 * \throw Kill_context_failed
-		 */
-		virtual void free_context(Signal_context_capability cap) = 0;
-
-
-		/*********************
-		 ** RPC declaration **
-		 *********************/
-
-		GENODE_RPC_THROW(Rpc_alloc_receiver, Signal_receiver_capability,
-		                 alloc_receiver, GENODE_TYPE_LIST(Out_of_metadata,
-		                 Create_receiver_failed));
-
-		GENODE_RPC_THROW(Rpc_alloc_context, Signal_context_capability,
-		                 alloc_context, GENODE_TYPE_LIST(Out_of_metadata,
-		                 Create_context_failed), Signal_receiver_capability,
-		                 unsigned);
-
-		GENODE_RPC_THROW(Rpc_free_receiver, void, free_receiver,
-		                 GENODE_TYPE_LIST(Kill_receiver_failed),
-		                 Signal_receiver_capability);
-
-		GENODE_RPC_THROW(Rpc_free_context, void, free_context,
-		                 GENODE_TYPE_LIST(Kill_context_failed),
-		                 Signal_context_capability);
-
-		GENODE_RPC_INTERFACE(Rpc_alloc_receiver, Rpc_alloc_context,
-		                     Rpc_free_receiver, Rpc_free_context);
-	};
-}
-
-#endif /* _INCLUDE__SIGNAL_SESSION__SIGNAL_SESSION_H_ */
-
diff --git a/repos/base-hw/lib/mk/core.inc b/repos/base-hw/lib/mk/core.inc
index 8fb2f06863..9e9dd9880b 100644
--- a/repos/base-hw/lib/mk/core.inc
+++ b/repos/base-hw/lib/mk/core.inc
@@ -30,6 +30,8 @@ SRC_CC += io_mem_session_support.cc
 SRC_CC += irq_session_component.cc
 SRC_CC += main.cc
 SRC_CC += pd_session_component.cc
+SRC_CC += pd_upgrade_ram_quota.cc
+SRC_CC += pd_assign_pci.cc
 SRC_CC += platform.cc
 SRC_CC += platform_pd.cc
 SRC_CC += platform_thread.cc
@@ -38,7 +40,6 @@ SRC_CC += ram_session_component.cc
 SRC_CC += ram_session_support.cc
 SRC_CC += rm_session_component.cc
 SRC_CC += rom_session_component.cc
-SRC_CC += signal_session_component.cc
 SRC_CC += trace_session_component.cc
 SRC_CC += thread_start.cc
 SRC_CC += env.cc
diff --git a/repos/base-hw/src/base/signal/signal.cc b/repos/base-hw/src/base/signal/signal.cc
index 7dcc2bd29a..1b66f54e60 100644
--- a/repos/base-hw/src/base/signal/signal.cc
+++ b/repos/base-hw/src/base/signal/signal.cc
@@ -12,9 +12,11 @@
  */
 
 /* Genode includes */
+#include <util/retry.h>
 #include <base/thread.h>
 #include <base/signal.h>
-#include <signal_session/connection.h>
+#include <base/env.h>
+#include <base/trace/events.h>
 
 /* base-hw includes */
 #include <kernel/interface.h>
@@ -46,33 +48,22 @@ void Signal_transmitter::submit(unsigned cnt)
 
 Signal_receiver::Signal_receiver()
 {
-	/* create a kernel object that corresponds to the receiver */
-	bool session_upgraded = 0;
-	Signal_connection * const s = signal_connection();
-	while (1) {
-		try {
-			_cap = s->alloc_receiver();
-			return;
-		} catch (Signal_session::Out_of_metadata)
-		{
-			/* upgrade session quota and try again, but only once */
-			if (session_upgraded) {
-				PERR("failed to alloc signal receiver");
-				_cap = Signal_receiver_capability();
-				return;
-			}
-			PINF("upgrading quota donation for SIGNAL session");
-			env()->parent()->upgrade(s->cap(), "ram_quota=8K");
-			session_upgraded = 1;
+	retry<Pd_session::Out_of_metadata>(
+		[&] () {
+			_cap = env()->pd_session()->alloc_signal_source();
+		},
+		[&] () {
+			PINF("upgrading quota donation for PD session");
+			env()->parent()->upgrade(env()->pd_session_cap(), "ram_quota=8K");
 		}
-	}
+	);
 }
 
 
 void Signal_receiver::_platform_destructor()
 {
 	/* release server resources of receiver */
-	signal_connection()->free_receiver(_cap);
+	env()->pd_session()->free_signal_source(_cap);
 }
 
 
@@ -91,27 +82,21 @@ Signal_context_capability Signal_receiver::manage(Signal_context * const c)
 	Lock::Guard context_guard(c->_lock);
 	if (c->_receiver) { throw Context_already_in_use(); }
 
-	/* create a context kernel-object at the receiver kernel-object */
-	bool session_upgraded = 0;
-	Signal_connection * const s = signal_connection();
-	while (1) {
-		try {
-			c->_cap = s->alloc_context(_cap, (unsigned long)c);
+	retry<Pd_session::Out_of_metadata>(
+		[&] () {
+			/* use signal context as imprint */
+			c->_cap = env()->pd_session()->alloc_context(_cap, (unsigned long)c);
 			c->_receiver = this;
 			_contexts.insert(&c->_receiver_le);
 			return c->_cap;
-		} catch (Signal_session::Out_of_metadata)
-		{
-			/* upgrade session quota and try again, but only once */
-			if (session_upgraded) {
-				PERR("failed to alloc signal context");
-				return Signal_context_capability();
-			}
-			PINF("upgrading quota donation for signal session");
-			env()->parent()->upgrade(s->cap(), "ram_quota=8K");
-			session_upgraded = 1;
+		},
+		[&] () {
+			PINF("upgrading quota donation for PD session");
+			env()->parent()->upgrade(env()->pd_session_cap(), "ram_quota=8K");
 		}
-	}
+	);
+
+	return c->_cap;
 }
 
 
diff --git a/repos/base-hw/src/core/include/pd_session_component.h b/repos/base-hw/src/core/include/pd_session_component.h
deleted file mode 100644
index 38e66651e9..0000000000
--- a/repos/base-hw/src/core/include/pd_session_component.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * \brief  Core-specific instance of the PD session interface
- * \author Christian Helmuth
- * \author Stefan Kalkowski
- * \date   2006-07-17
- */
-
-/*
- * 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.
- */
-
-#ifndef _CORE__INCLUDE__PD_SESSION_COMPONENT_H_
-#define _CORE__INCLUDE__PD_SESSION_COMPONENT_H_
-
-/* Genode includes */
-#include <base/allocator_guard.h>
-#include <base/rpc_server.h>
-#include <pd_session/pd_session.h>
-#include <util/arg_string.h>
-
-/* core includes */
-#include <platform_pd.h>
-
-namespace Genode { class Pd_session_component; }
-
-
-class Genode::Pd_session_component : public Rpc_object<Pd_session>
-{
-	private:
-
-		/**
-		 * Read and store the PD label
-		 */
-		struct Label {
-
-			enum { MAX_LEN = 64 };
-			char string[MAX_LEN];
-
-			Label(char const *args)
-			{
-				Arg_string::find_arg(args, "label").string(string,
-				                                           sizeof(string), "");
-			}
-		} const _label;
-
-		Allocator_guard    _md_alloc;   /* guarded meta-data allocator */
-		Platform_pd        _pd;
-		Parent_capability  _parent;
-		Rpc_entrypoint    *_thread_ep;
-
-		size_t _ram_quota(char const * args) {
-			return Arg_string::find_arg(args, "ram_quota").long_value(0); }
-
-	public:
-
-		Pd_session_component(Rpc_entrypoint * thread_ep,
-		                     Allocator      * md_alloc,
-		                     char const     * args)
-		: _label(args),
-		  _md_alloc(md_alloc, _ram_quota(args)),
-		  _pd(&_md_alloc, _label.string),
-		  _thread_ep(thread_ep) { }
-
-		/**
-		 * Register quota donation at allocator guard
-		 */
-		void upgrade_ram_quota(size_t ram_quota)
-		{
-			_md_alloc.upgrade(ram_quota);
-			_pd.upgrade_slab(_md_alloc);
-		}
-
-
-		/**************************/
-		/** PD session interface **/
-		/**************************/
-
-		int bind_thread(Thread_capability);
-		int assign_parent(Parent_capability);
-};
-
-#endif /* _CORE__INCLUDE__PD_SESSION_COMPONENT_H_ */
diff --git a/repos/base-hw/src/core/include/signal_broker.h b/repos/base-hw/src/core/include/signal_broker.h
new file mode 100644
index 0000000000..05139725c6
--- /dev/null
+++ b/repos/base-hw/src/core/include/signal_broker.h
@@ -0,0 +1,152 @@
+/*
+ * \brief  Base-hw-specific signal-delivery mechanism
+ * \author Norman Feske
+ * \date   2016-01-04
+ */
+
+/*
+ * Copyright (C) 2016 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__SIGNAL_BROKER_H_
+#define _CORE__INCLUDE__SIGNAL_BROKER_H_
+
+/* Genode includes */
+#include <base/tslab.h>
+
+/* core-local includes */
+#include <assertion.h>
+#include <signal_source_component.h>
+
+namespace Genode { class Signal_broker; }
+
+
+class Genode::Signal_broker
+{
+	private:
+
+		template <typename T, size_t BLOCK_SIZE = get_page_size()>
+		class Slab : public Tslab<T, BLOCK_SIZE>
+		{
+			private:
+
+				uint8_t _first_block[BLOCK_SIZE];
+
+			public:
+
+				Slab(Allocator * const allocator)
+				: Tslab<T, BLOCK_SIZE>(allocator,
+				                       (Slab_block*)&_first_block) { }
+		};
+
+		Allocator                     &_md_alloc;
+		Slab<Signal_source_component>  _sources_slab { &_md_alloc };
+		Signal_source_pool             _sources;
+		Slab<Signal_context_component> _contexts_slab { &_md_alloc };
+		Signal_context_pool            _contexts;
+
+	public:
+
+		class Invalid_signal_source : public Exception { };
+
+		Signal_broker(Allocator &md_alloc, Rpc_entrypoint &, Rpc_entrypoint &)
+		:
+			_md_alloc(md_alloc)
+		{ }
+
+		~Signal_broker()
+		{
+			_contexts.remove_all([this] (Signal_context_component *c) {
+				destroy(&_contexts_slab, c);});
+			_sources.remove_all([this] (Signal_source_component *s) {
+				destroy(&_sources_slab, s);});
+		}
+
+		/*
+		 * \throw Allocator::Out_of_memory
+		 */
+		Capability<Signal_source> alloc_signal_source()
+		{
+			/* the _sources_slab may throw Allocator::Out_of_memory */
+			Signal_source_component *s = new (_sources_slab) Signal_source_component();
+			_sources.insert(s);
+			return reinterpret_cap_cast<Signal_source>(s->cap());
+		}
+
+		void free_signal_source(Capability<Signal_source> cap)
+		{
+			Signal_source_component *source = nullptr;
+			auto lambda = [&] (Signal_source_component *s) {
+
+				if (!s) {
+					PERR("unknown signal source");
+					return;
+				}
+
+				source = s;
+				_sources.remove(source);
+			};
+			_sources.apply(cap, lambda);
+
+			/* destruct signal source outside the lambda to prevent deadlock */
+			if (source)
+				destroy(&_sources_slab, source);
+		}
+
+		/*
+		 * \throw Allocator::Out_of_memory
+		 * \throw Invalid_signal_source
+		 */
+		Signal_context_capability
+		alloc_context(Capability<Signal_source> source, unsigned long imprint)
+		{
+			auto lambda = [&] (Signal_source_component *s) {
+				if (!s) {
+					PERR("unknown signal source");
+					throw Invalid_signal_source();
+				}
+
+				/* the _contexts_slab may throw Allocator::Out_of_memory */
+				Signal_context_component *c = new (_contexts_slab)
+					Signal_context_component(*s, imprint);
+
+				_contexts.insert(c);
+				return reinterpret_cap_cast<Signal_context>(c->cap());
+			};
+			return _sources.apply(source, lambda);
+		}
+
+		void free_context(Signal_context_capability context_cap)
+		{
+			Signal_context_component *context = nullptr;
+			auto lambda = [&] (Signal_context_component *c) {
+
+				if (!c) {
+					PERR("unknown signal context");
+					return;
+				}
+
+				context = c;
+				_contexts.remove(context);
+			};
+
+			_contexts.apply(context_cap, lambda);
+
+			/* destruct context outside the lambda to prevent deadlock */
+			if (context)
+				destroy(&_contexts_slab, context);
+		}
+
+		void submit(Signal_context_capability cap, unsigned cnt)
+		{
+			/*
+			 * This function is never called as base-hw delivers signals
+			 * directly via the kernel.
+			 */
+		}
+};
+
+#endif /* _CORE__INCLUDE__SIGNAL_BROKER_H_ */
diff --git a/repos/base-hw/src/core/include/signal_root.h b/repos/base-hw/src/core/include/signal_root.h
deleted file mode 100644
index f79053988a..0000000000
--- a/repos/base-hw/src/core/include/signal_root.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * \brief  Signal root interface on HW-core
- * \author Martin Stein
- * \date   2012-05-06
- */
-
-/*
- * Copyright (C) 2012-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__SIGNAL_ROOT_H_
-#define _CORE__INCLUDE__SIGNAL_ROOT_H_
-
-/* Genode includes */
-#include <root/component.h>
-
-/* base-hw includes */
-#include <kernel/core_interface.h>
-
-/* core includes */
-#include <signal_session_component.h>
-
-namespace Genode
-{
-	/**
-	 * Provide EP to signal root before it initialises root component
-	 */
-	class Signal_handler
-	{
-		enum { STACK_SIZE = 1024 * sizeof(addr_t) };
-
-		Rpc_entrypoint _entrypoint;
-
-		public:
-
-			/**
-			 * Constructor
-			 */
-			Signal_handler(Cap_session * const c)
-			: _entrypoint(c, STACK_SIZE, "signal") { }
-
-			/***************
-			 ** Accessors **
-			 ***************/
-
-			Rpc_entrypoint * entrypoint() { return &_entrypoint; }
-	};
-
-	/**
-	 * Provides signal service by managing appropriate sessions to the clients
-	 */
-	class Signal_root : private Signal_handler,
-	                    public  Root_component<Signal_session_component>
-	{
-		public:
-
-			/**
-			 * Constructor
-			 *
-			 * \param md  Meta-data allocator to be used by root component
-			 * \param c   CAP session to be used by the root entrypoint
-			 */
-			Signal_root(Allocator * const md, Cap_session * const c) :
-				Signal_handler(c),
-				Root_component<Signal_session_component>(entrypoint(), md)
-			{ }
-
-		protected:
-
-			/********************************
-			 ** 'Root_component' interface **
-			 ********************************/
-
-			Signal_session_component * _create_session(const char * args)
-			{
-				size_t ram_quota =
-					Arg_string::find_arg(args, "ram_quota").ulong_value(0);
-				return new (md_alloc())
-					Signal_session_component(md_alloc(), ram_quota);
-			}
-
-			void _upgrade_session(Signal_session_component *s,
-			                      const char * args)
-			{
-				size_t ram_quota =
-					Arg_string::find_arg(args, "ram_quota").ulong_value(0);
-				s->upgrade_ram_quota(ram_quota);
-			}
-	};
-}
-
-#endif /* _CORE__INCLUDE__SIGNAL_ROOT_H_ */
-
diff --git a/repos/base-hw/src/core/include/signal_session_component.h b/repos/base-hw/src/core/include/signal_session_component.h
deleted file mode 100644
index bd328695c5..0000000000
--- a/repos/base-hw/src/core/include/signal_session_component.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * \brief  Server-sided implementation of a signal session
- * \author Martin stein
- * \date   2012-05-05
- */
-
-/*
- * Copyright (C) 2012-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__SIGNAL_SESSION_COMPONENT_H_
-#define _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_
-
-/* Genode includes */
-#include <signal_session/signal_session.h>
-#include <base/rpc_server.h>
-#include <base/tslab.h>
-#include <base/allocator_guard.h>
-#include <base/object_pool.h>
-
-/* core includes */
-#include <object.h>
-#include <kernel/signal_receiver.h>
-#include <util.h>
-
-namespace Genode
-{
-	/**
-	 * Server-side implementation of a signal session
-	 */
-	class Signal_session_component;
-}
-
-
-
-class Genode::Signal_session_component : public Rpc_object<Signal_session>
-{
-	private:
-
-		struct Receiver : Kernel_object<Kernel::Signal_receiver>,
-		                  Object_pool<Receiver>::Entry
-		{
-			using Pool = Object_pool<Receiver>;
-
-			Receiver();
-		};
-
-
-		struct Context : Kernel_object<Kernel::Signal_context>,
-		                 Object_pool<Context>::Entry
-		{
-			using Pool = Object_pool<Context>;
-
-			Context(Receiver &rcv, unsigned const imprint);
-		};
-
-		template <typename T, size_t BLOCK_SIZE = get_page_size()>
-		class Slab : public Tslab<T, BLOCK_SIZE>
-		{
-			private:
-
-				uint8_t _first_block[BLOCK_SIZE];
-
-			public:
-
-				Slab(Allocator * const allocator)
-				: Tslab<T, BLOCK_SIZE>(allocator,
-				                       (Slab_block*)&_first_block) { }
-		};
-
-
-		Allocator_guard  _allocator;
-		Slab<Receiver>   _receivers_slab;
-		Receiver::Pool   _receivers;
-		Slab<Context>    _contexts_slab;
-		Context::Pool    _contexts;
-
-		/**
-		 * Destruct receiver 'r'
-		 */
-		void _destruct_receiver(Receiver * const r);
-
-		/**
-		 * Destruct context 'c'
-		 */
-		void _destruct_context(Context * const c);
-
-	public:
-
-		/**
-		 * Constructor
-		 *
-		 * \param allocator  RAM allocator for meta data
-		 * \param quota      amount of RAM quota donated to this session
-		 */
-		Signal_session_component(Allocator * const allocator,
-		                         size_t const quota);
-
-		~Signal_session_component();
-
-		/**
-		 * Raise the quota of this session by 'q'
-		 */
-		void upgrade_ram_quota(size_t const q) { _allocator.upgrade(q); }
-
-
-		/******************************
-		 ** Signal_session interface **
-		 ******************************/
-
-		Signal_receiver_capability alloc_receiver();
-
-		Signal_context_capability
-		alloc_context(Signal_receiver_capability, unsigned const);
-
-		void free_receiver(Signal_receiver_capability);
-
-		void free_context(Signal_context_capability);
-};
-
-#endif /* _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_ */
diff --git a/repos/base-hw/src/core/include/signal_source_component.h b/repos/base-hw/src/core/include/signal_source_component.h
new file mode 100644
index 0000000000..60e9392480
--- /dev/null
+++ b/repos/base-hw/src/core/include/signal_source_component.h
@@ -0,0 +1,65 @@
+/*
+ * \brief  Signal-delivery mechanism
+ * \author Norman Feske
+ * \date   2009-08-05
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_
+#define _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_
+
+/* Genode includes */
+#include <base/object_pool.h>
+
+/* core-local includes */
+#include <object.h>
+#include <kernel/signal_receiver.h>
+#include <assertion.h>
+
+namespace Genode {
+
+	class Signal_context_component;
+	class Signal_source_component;
+
+	typedef Object_pool<Signal_context_component> Signal_context_pool;
+	typedef Object_pool<Signal_source_component>  Signal_source_pool;
+}
+
+
+struct Genode::Signal_context_component : Kernel_object<Kernel::Signal_context>,
+                                          Signal_context_pool::Entry
+{
+	inline Signal_context_component(Signal_source_component &s,
+	                                unsigned long const imprint);
+
+	Signal_source_component *source() { ASSERT_NEVER_CALLED; }
+};
+
+
+struct Genode::Signal_source_component : Kernel_object<Kernel::Signal_receiver>,
+                                         Signal_source_pool::Entry
+{
+	Signal_source_component()
+	:
+		Kernel_object<Kernel::Signal_receiver>(true),
+		Signal_source_pool::Entry(Kernel_object<Kernel::Signal_receiver>::_cap)
+	{ }
+
+	void submit(Signal_context_component *, unsigned long) { ASSERT_NEVER_CALLED; }
+};
+
+
+Genode::Signal_context_component::Signal_context_component(Signal_source_component &s,
+                                                           unsigned long const imprint)
+:
+	Kernel_object<Kernel::Signal_context>(true, s.kernel_object(), imprint),
+	Signal_context_pool::Entry(Kernel_object<Kernel::Signal_context>::_cap)
+{ }
+
+#endif /* _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_ */
diff --git a/repos/base-hw/src/core/pd_upgrade_ram_quota.cc b/repos/base-hw/src/core/pd_upgrade_ram_quota.cc
new file mode 100644
index 0000000000..84962cb8f5
--- /dev/null
+++ b/repos/base-hw/src/core/pd_upgrade_ram_quota.cc
@@ -0,0 +1,25 @@
+/*
+ * \brief  Core implementation of the PD session interface
+ * \author Norman Feske
+ * \date   2016-01-13
+ */
+
+/*
+ * Copyright (C) 2016 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-local includes */
+#include <pd_session_component.h>
+
+using namespace Genode;
+
+
+void Pd_session_component::upgrade_ram_quota(size_t ram_quota)
+{
+	_md_alloc.upgrade(ram_quota);
+	_pd.upgrade_slab(_md_alloc);
+}
+
diff --git a/repos/base-hw/src/core/signal_session_component.cc b/repos/base-hw/src/core/signal_session_component.cc
deleted file mode 100644
index f53f6432ef..0000000000
--- a/repos/base-hw/src/core/signal_session_component.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * \brief  Implementation of the SIGNAL service on the HW-core
- * \author Martin Stein
- * \date   2012-05-05
- */
-
-/*
- * Copyright (C) 2012-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 <base/printf.h>
-#include <unmanaged_singleton.h>
-
-/* base-hw includes */
-#include <kernel/core_interface.h>
-
-/* core includes */
-#include <signal_session_component.h>
-
-using namespace Genode;
-
-
-Signal_session_component::Receiver::Receiver()
-: Kernel_object<Kernel::Signal_receiver>(true),
-  Signal_session_component::Receiver::Pool::Entry(Kernel_object<Kernel::Signal_receiver>::_cap) { }
-
-
-Signal_session_component::Context::Context(Signal_session_component::Receiver &r,
-                                           unsigned const imprint)
-: Kernel_object<Kernel::Signal_context>(true, r.kernel_object(), imprint),
-  Signal_session_component::Context::Pool::Entry(Kernel_object<Kernel::Signal_context>::_cap) { }
-
-
-Signal_receiver_capability Signal_session_component::alloc_receiver()
-{
-	try {
-		Receiver * r = new (_receivers_slab) Receiver();
-		_receivers.insert(r);
-		return reinterpret_cap_cast<Signal_receiver>(r->cap());
-	} catch (Allocator::Out_of_memory&) {
-		PERR("failed to allocate signal-receiver resources");
-		throw Out_of_metadata();
-	}
-	return reinterpret_cap_cast<Signal_receiver>(Untyped_capability());
-}
-
-
-void Signal_session_component::free_receiver(Signal_receiver_capability cap)
-{
-	/* look up ressource info */
-	Receiver * receiver;
-	auto lambda = [&] (Receiver *r) {
-		receiver = r;
-		if (!receiver) {
-			PERR("unknown signal receiver");
-			throw Kill_receiver_failed();
-		}
-		/* release resources */
-		_receivers.remove(receiver);
-	};
-	_receivers.apply(cap, lambda);
-	destroy(&_receivers_slab, receiver);
-}
-
-
-Signal_context_capability
-Signal_session_component::alloc_context(Signal_receiver_capability src,
-                                        unsigned const imprint)
-{
-	/* look up ressource info */
-	auto lambda = [&] (Receiver *r) {
-		if (!r) {
-			PERR("unknown signal receiver");
-			throw Create_context_failed();
-		}
-
-		try {
-			Context * c = new (_contexts_slab) Context(*r, imprint);
-			_contexts.insert(c);
-			return reinterpret_cap_cast<Signal_context>(c->cap());
-		} catch (Allocator::Out_of_memory&) {
-			PERR("failed to allocate signal-context resources");
-			throw Out_of_metadata();
-		}
-		return reinterpret_cap_cast<Signal_context>(Untyped_capability());
-	};
-	return _receivers.apply(src, lambda);
-}
-
-
-void Signal_session_component::free_context(Signal_context_capability cap)
-{
-	/* look up ressource info */
-	Context * context;
-	auto lambda = [&] (Context *c) {
-		context = c;
-		if (!context) {
-			PERR("unknown signal context");
-			throw Kill_context_failed();
-		}
-		/* release resources */
-		_contexts.remove(context);
-	};
-	_contexts.apply(cap, lambda);
-	destroy(&_contexts_slab, context);
-}
-
-
-Signal_session_component::Signal_session_component(Allocator * const allocator,
-                                                   size_t const quota)
-: _allocator(allocator, quota), _receivers_slab(&_allocator),
-  _contexts_slab(&_allocator) { }
-
-
-Signal_session_component::~Signal_session_component()
-{
-	_contexts.remove_all([this] (Context * c) {
-		destroy(&_contexts_slab, c);});
-	_receivers.remove_all([this] (Receiver * r) {
-		destroy(&_receivers_slab, r);});
-}
diff --git a/repos/base-hw/src/test/cpu_quota/include/sync_session/sync_session.h b/repos/base-hw/src/test/cpu_quota/include/sync_session/sync_session.h
index 7400757745..25d4137fec 100644
--- a/repos/base-hw/src/test/cpu_quota/include/sync_session/sync_session.h
+++ b/repos/base-hw/src/test/cpu_quota/include/sync_session/sync_session.h
@@ -16,7 +16,7 @@
 
 /* Genode includes */
 #include <session/session.h>
-#include <signal_session/signal_session.h>
+#include <base/signal.h>
 
 namespace Sync
 {
diff --git a/repos/base-linux/include/linux_pd_session/client.h b/repos/base-linux/include/linux_pd_session/client.h
index d3c183870d..07302706d5 100644
--- a/repos/base-linux/include/linux_pd_session/client.h
+++ b/repos/base-linux/include/linux_pd_session/client.h
@@ -17,27 +17,45 @@
 #include <linux_pd_session/linux_pd_session.h>
 #include <base/rpc_client.h>
 
-namespace Genode {
+namespace Genode { struct Linux_pd_session_client; }
 
-	struct Linux_pd_session_client : Rpc_client<Linux_pd_session>
-	{
-		explicit Linux_pd_session_client(Capability<Linux_pd_session> session)
-		: Rpc_client<Linux_pd_session>(session) { }
+struct Genode::Linux_pd_session_client : Rpc_client<Linux_pd_session>
+{
+	explicit Linux_pd_session_client(Capability<Linux_pd_session> session)
+	: Rpc_client<Linux_pd_session>(session) { }
 
-		int bind_thread(Thread_capability thread) {
-			return call<Rpc_bind_thread>(thread); }
+	int bind_thread(Thread_capability thread) override {
+		return call<Rpc_bind_thread>(thread); }
 
-		int assign_parent(Parent_capability parent) {
-			return call<Rpc_assign_parent>(parent); }
+	int assign_parent(Capability<Parent> parent) override {
+		return call<Rpc_assign_parent>(parent); }
+
+	bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) override {
+		return call<Rpc_assign_pci>(pci_config_memory_address, bdf); }
+
+	Signal_source_capability alloc_signal_source() override {
+		return call<Rpc_alloc_signal_source>(); }
+
+	void free_signal_source(Signal_source_capability cap) override {
+		call<Rpc_free_signal_source>(cap); }
+
+	Signal_context_capability alloc_context(Signal_source_capability source,
+	                                        unsigned long imprint) override {
+		return call<Rpc_alloc_context>(source, imprint); }
+
+	void free_context(Signal_context_capability cap) override {
+		call<Rpc_free_context>(cap); }
+
+	void submit(Signal_context_capability receiver, unsigned cnt = 1) override {
+		call<Rpc_submit>(receiver, cnt); }
 
 
-		/*****************************
-		 * Linux-specific extension **
-		 *****************************/
+	/*****************************
+	 * Linux-specific extension **
+	 *****************************/
 
-		void start(Capability<Dataspace> binary) {
-			call<Rpc_start>(binary); }
-	};
-}
+	void start(Capability<Dataspace> binary) {
+		call<Rpc_start>(binary); }
+};
 
 #endif /* _INCLUDE__LINUX_PD_SESSION__CLIENT_H_ */
diff --git a/repos/base-linux/src/base/env/platform_env.h b/repos/base-linux/src/base/env/platform_env.h
index 7d3dc045cd..b8b33d1c9c 100644
--- a/repos/base-linux/src/base/env/platform_env.h
+++ b/repos/base-linux/src/base/env/platform_env.h
@@ -323,6 +323,7 @@ namespace Genode {
 			Cpu_session_capability       _cpu_session_cap;
 			Expanding_cpu_session_client _cpu_session_client;
 			Rm_session_mmap              _rm_session_mmap;
+			Pd_session_capability        _pd_session_cap;
 			Pd_session_client            _pd_session_client;
 
 		public:
@@ -339,7 +340,8 @@ namespace Genode {
 				_cpu_session_cap(cpu_cap),
 				_cpu_session_client(static_cap_cast<Linux_cpu_session>(cpu_cap)),
 				_rm_session_mmap(false),
-				_pd_session_client(pd_cap)
+				_pd_session_cap(pd_cap),
+				_pd_session_client(_pd_session_cap)
 			{ }
 
 
@@ -347,12 +349,13 @@ namespace Genode {
 			 ** Env interface **
 			 *******************/
 
-			Ram_session            *ram_session()     { return &_ram_session_client; }
-			Ram_session_capability  ram_session_cap() { return  _ram_session_cap; }
-			Rm_session             *rm_session()      { return &_rm_session_mmap; }
-			Linux_cpu_session      *cpu_session()     { return &_cpu_session_client; }
-			Cpu_session_capability  cpu_session_cap() { return  _cpu_session_cap; }
-			Pd_session             *pd_session()      { return &_pd_session_client; }
+			Ram_session            *ram_session()     override { return &_ram_session_client; }
+			Ram_session_capability  ram_session_cap() override { return  _ram_session_cap; }
+			Rm_session             *rm_session()      override { return &_rm_session_mmap; }
+			Linux_cpu_session      *cpu_session()     override { return &_cpu_session_client; }
+			Cpu_session_capability  cpu_session_cap() override { return  _cpu_session_cap; }
+			Pd_session             *pd_session()      override { return &_pd_session_client; }
+			Pd_session_capability   pd_session_cap()  override { return  _pd_session_cap; }
 
 			/*
 			 * Support functions for implementing fork on Noux.
@@ -451,8 +454,8 @@ namespace Genode {
 			 ** Env interface **
 			 *******************/
 
-			Parent *parent() { return &_parent(); }
-			Heap   *heap()   { return &_heap; }
+			Parent      *parent()      override { return &_parent(); }
+			Heap        *heap()        override { return &_heap; }
 	};
 }
 
diff --git a/repos/base-linux/src/core/include/core_env.h b/repos/base-linux/src/core/include/core_env.h
index d4576727b0..67bcb6a0dc 100644
--- a/repos/base-linux/src/core/include/core_env.h
+++ b/repos/base-linux/src/core/include/core_env.h
@@ -23,6 +23,7 @@
 #include <core_parent.h>
 #include <cap_session_component.h>
 #include <ram_session_component.h>
+#include <core_pd_session.h>
 
 /* internal base includes */
 #include <platform_env.h>
@@ -140,6 +141,17 @@ namespace Genode {
 			Cap_session_component        _cap_session;
 			Entrypoint                   _entrypoint;
 			Core_ram_session             _ram_session;
+
+			/*
+			 * The core-local PD session is provided by a real RPC object
+			 * dispatched by the same entrypoint as the signal-source RPC
+			 * objects. This is needed to allow the 'Pd_session::submit'
+			 * method to issue out-of-order replies to
+			 * 'Signal_source::wait_for_signal' calls.
+			 */
+			Core_pd_session_component _pd_session_component;
+			Pd_session_client         _pd_session_client;
+
 			Heap                         _heap;
 			Ram_session_capability const _ram_session_cap;
 
@@ -158,6 +170,8 @@ namespace Genode {
 				_ram_session(&_entrypoint, &_entrypoint,
 				             platform()->ram_alloc(), platform()->core_mem_alloc(),
 				             "ram_quota=4M", platform()->ram_alloc()->avail()),
+				_pd_session_component(_entrypoint /* XXX use a different entrypoint */),
+				_pd_session_client(_entrypoint.manage(&_pd_session_component)),
 				_heap(&_ram_session, Platform_env_base::rm_session()),
 				_ram_session_cap(_entrypoint.manage(&_ram_session))
 			{ }
@@ -183,6 +197,7 @@ namespace Genode {
 			Parent                 *parent()          { return &_core_parent; }
 			Ram_session            *ram_session()     { return &_ram_session; }
 			Ram_session_capability  ram_session_cap() { return  _ram_session_cap; }
+			Pd_session             *pd_session()      { return &_pd_session_client; }
 			Allocator              *heap()            { return &_heap; }
 
 			Cpu_session_capability cpu_session_cap() {
@@ -190,12 +205,6 @@ namespace Genode {
 				return Cpu_session_capability();
 			}
 
-			Pd_session *pd_session()
-			{
-				PWRN("%s:%u not implemented", __FILE__, __LINE__);
-				return 0;
-			}
-
 			void reload_parent_cap(Capability<Parent>::Dst, long) { }
 	};
 
diff --git a/repos/base-linux/src/core/include/pd_session_component.h b/repos/base-linux/src/core/include/pd_session_component.h
index 0ace51f22e..e4e0623b57 100644
--- a/repos/base-linux/src/core/include/pd_session_component.h
+++ b/repos/base-linux/src/core/include/pd_session_component.h
@@ -21,61 +21,92 @@
 
 /* core includes */
 #include <platform_pd.h>
+#include <signal_broker.h>
 
 namespace Genode {
 
 	class Dataspace_component;
-	class Pd_session_component : public Rpc_object<Linux_pd_session, Pd_session_component>
-	{
-		private:
-
-			enum { LABEL_MAX_LEN     = 1024 };
-			enum { ROOT_PATH_MAX_LEN =  512 };
-
-			unsigned long      _pid;
-			char               _label[LABEL_MAX_LEN];
-			char               _root[ROOT_PATH_MAX_LEN];
-			unsigned           _uid;
-			unsigned           _gid;
-			Parent_capability  _parent;
-			Rpc_entrypoint    *_ds_ep;
-
-			void _start(Dataspace_component *ds);
-
-		public:
-
-			/**
-			 * Constructor
-			 *
-			 * \param ds_ep     entrypoint where the dataspaces are managed
-			 * \param md_alloc  meta-data allocator
-			 * \param args      additional session arguments
-			 */
-			Pd_session_component(Rpc_entrypoint *ds_ep, Allocator * md_alloc,
-			                     const char *args);
-
-			~Pd_session_component();
-
-			/**
-			 * Register quota donation at allocator guard
-			 */
-			void upgrade_ram_quota(size_t ram_quota) { }
-
-
-			/**************************
-			 ** PD session interface **
-			 **************************/
-
-			int bind_thread(Thread_capability);
-			int assign_parent(Parent_capability parent);
-
-
-			/******************************
-			 ** Linux-specific extension **
-			 ******************************/
-
-			void start(Capability<Dataspace> binary);
-	};
+	class Pd_session_component;
+	class Parent;
 }
 
+
+class Genode::Pd_session_component : public Rpc_object<Linux_pd_session, Pd_session_component>
+{
+	private:
+
+		enum { LABEL_MAX_LEN     = 1024 };
+		enum { ROOT_PATH_MAX_LEN =  512 };
+
+		unsigned long      _pid;
+		char               _label[LABEL_MAX_LEN];
+		char               _root[ROOT_PATH_MAX_LEN];
+		unsigned           _uid;
+		unsigned           _gid;
+		Capability<Parent> _parent;
+		Rpc_entrypoint    &_ds_ep;
+		Signal_broker      _signal_broker;
+
+		void _start(Dataspace_component *ds);
+
+	public:
+
+		/**
+		 * Constructor
+		 *
+		 * \param ds_ep        entrypoint where the dataspaces are managed
+		 * \param receiver_ep  entrypoint holding signal-receiver component
+		 *                     objects
+		 * \param context_ep   global pool of all signal contexts
+		 * \param md_alloc     meta-data allocator
+		 * \param args         additional session arguments
+		 */
+		Pd_session_component(Rpc_entrypoint &ds_ep,
+		                     Rpc_entrypoint &receiver_ep,
+		                     Rpc_entrypoint &context_ep,
+		                     Allocator &md_alloc,
+		                     const char *args);
+
+		~Pd_session_component();
+
+		/**
+		 * Register quota donation at allocator guard
+		 */
+		void upgrade_ram_quota(size_t ram_quota) { }
+
+
+		/**************************
+		 ** PD session interface **
+		 **************************/
+
+		int bind_thread(Thread_capability);
+		int assign_parent(Capability<Parent>);
+		bool assign_pci(addr_t, uint16_t) { return false; }
+
+		Signal_source_capability alloc_signal_source() override {
+			return _signal_broker.alloc_signal_source(); }
+
+		void free_signal_source(Signal_source_capability cap) override {
+			_signal_broker.free_signal_source(cap); }
+
+		Signal_context_capability
+		alloc_context(Signal_source_capability sig_rec_cap, unsigned long imprint) override
+		{
+			return _signal_broker.alloc_context(sig_rec_cap, imprint);
+		}
+
+		void free_context(Signal_context_capability cap) override {
+			_signal_broker.free_context(cap); }
+
+		void submit(Signal_context_capability cap, unsigned n) override {
+			_signal_broker.submit(cap, n); }
+
+
+		/******************************
+		 ** Linux-specific extension **
+		 ******************************/
+
+		void start(Capability<Dataspace> binary);
+};
+
 #endif /* _CORE__INCLUDE__PD_SESSION_COMPONENT_H_ */
diff --git a/repos/base-linux/src/core/pd_session_component.cc b/repos/base-linux/src/core/pd_session_component.cc
index 5d5c986c94..3f2548275c 100644
--- a/repos/base-linux/src/core/pd_session_component.cc
+++ b/repos/base-linux/src/core/pd_session_component.cc
@@ -397,11 +397,14 @@ void Pd_session_component::_start(Dataspace_component *ds)
 }
 
 
-Pd_session_component::Pd_session_component(Rpc_entrypoint * ep,
-                                           Allocator      * md_alloc,
-                                           const char     * args)
+Pd_session_component::Pd_session_component(Rpc_entrypoint &ds_ep,
+                                           Rpc_entrypoint &receiver_ep,
+                                           Rpc_entrypoint &context_ep,
+                                           Allocator      &md_alloc,
+                                           const char     *args)
 :
-	_pid(0), _uid(0), _gid(0), _ds_ep(ep)
+	_pid(0), _uid(0), _gid(0), _ds_ep(ds_ep),
+	_signal_broker(md_alloc, receiver_ep, context_ep)
 {
 	Arg_string::find_arg(args, "label").string(_label, sizeof(_label),
 	                                           "<unlabeled>");
@@ -449,7 +452,7 @@ Pd_session_component::~Pd_session_component()
 int Pd_session_component::bind_thread(Thread_capability) { return -1; }
 
 
-int Pd_session_component::assign_parent(Parent_capability parent)
+int Pd_session_component::assign_parent(Capability<Parent> parent)
 {
 	_parent = parent;
 	return 0;
@@ -459,6 +462,6 @@ int Pd_session_component::assign_parent(Parent_capability parent)
 void Pd_session_component::start(Capability<Dataspace> binary)
 {
 	/* lookup binary dataspace */
-	_ds_ep->apply(binary, [&] (Dataspace_component *ds) {
+	_ds_ep.apply(binary, [&] (Dataspace_component *ds) {
 		_start(ds); });
 };
diff --git a/repos/base-linux/src/core/target.mk b/repos/base-linux/src/core/target.mk
index 7d7e4a741c..428a5d9e56 100644
--- a/repos/base-linux/src/core/target.mk
+++ b/repos/base-linux/src/core/target.mk
@@ -18,7 +18,6 @@ SRC_CC        = main.cc \
                 dataspace_component.cc \
                 pd_session_component.cc \
                 io_mem_session_component.cc \
-                signal_session_component.cc \
                 signal_source_component.cc \
                 trace_session_component.cc \
                 thread_linux.cc \
@@ -44,7 +43,6 @@ vpath ram_session_component.cc    $(GEN_CORE_DIR)
 vpath cap_session_component.cc    $(GEN_CORE_DIR)
 vpath cpu_session_component.cc    $(GEN_CORE_DIR)
 vpath platform_services.cc        $(GEN_CORE_DIR)
-vpath signal_session_component.cc $(GEN_CORE_DIR)
 vpath signal_source_component.cc  $(GEN_CORE_DIR)
 vpath trace_session_component.cc  $(GEN_CORE_DIR)
 vpath core_printf.cc              $(BASE_DIR)/src/base/console
diff --git a/repos/base-nova/include/pd_session/client.h b/repos/base-nova/include/pd_session/client.h
index 9a29860dde..f874badb2c 100644
--- a/repos/base-nova/include/pd_session/client.h
+++ b/repos/base-nova/include/pd_session/client.h
@@ -17,25 +17,52 @@
 #include <pd_session/capability.h>
 #include <base/rpc_client.h>
 
-namespace Genode {
+namespace Genode { struct Pd_session_client; }
 
-	struct Pd_session_client : Rpc_client<Pd_session>
+
+/*
+ * This implementation overrides the corresponding header in base/include
+ * to tweak the way the parent capability is passed to core.
+ */
+struct Genode::Pd_session_client : Rpc_client<Pd_session>
+{
+	explicit Pd_session_client(Pd_session_capability session)
+	: Rpc_client<Pd_session>(session) { }
+
+	int bind_thread(Thread_capability thread) override {
+		return call<Rpc_bind_thread>(thread); }
+
+	int assign_parent(Capability<Parent> parent) override
 	{
-		explicit Pd_session_client(Pd_session_capability session)
-		: Rpc_client<Pd_session>(session) { }
+		/*
+		 * NOVA-specific implementation
+		 *
+		 * We need to prevent NOVA from creating a new branch in the mapping
+		 * tree. Instead, we need core to re-associate the supplied PD cap with
+		 * the core-known PD session component of the parent.
+		 */
+		parent.solely_map();
+		return call<Rpc_assign_parent>(parent);
+	}
 
-		int bind_thread(Thread_capability thread) {
-			return call<Rpc_bind_thread>(thread); }
+	bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) override {
+		return call<Rpc_assign_pci>(pci_config_memory_address, bdf); }
 
-		int assign_parent(Parent_capability parent)
-		{
-			parent.solely_map();
-			return call<Rpc_assign_parent>(parent);
-		}
+	Signal_source_capability alloc_signal_source() override {
+		return call<Rpc_alloc_signal_source>(); }
 
-		bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) {
-			return call<Rpc_assign_pci>(pci_config_memory_address, bdf); }
-	};
-}
+	void free_signal_source(Signal_source_capability cap) override {
+		call<Rpc_free_signal_source>(cap); }
+
+	Signal_context_capability alloc_context(Signal_source_capability source,
+	                                        unsigned long imprint) override {
+		return call<Rpc_alloc_context>(source, imprint); }
+
+	void free_context(Signal_context_capability cap) override {
+		call<Rpc_free_context>(cap); }
+
+	void submit(Signal_context_capability receiver, unsigned cnt = 1) override {
+		call<Rpc_submit>(receiver, cnt); }
+};
 
 #endif /* _INCLUDE__PD_SESSION__CLIENT_H_ */
diff --git a/repos/base-nova/include/pd_session/pd_session.h b/repos/base-nova/include/pd_session/pd_session.h
deleted file mode 100644
index efa573acc4..0000000000
--- a/repos/base-nova/include/pd_session/pd_session.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * \brief  Protection domain (PD) session interface
- * \author Christian Helmuth
- * \date   2006-06-27
- *
- * A pd session represents the protection domain of a program.
- */
-
-/*
- * 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.
- */
-
-#ifndef _INCLUDE__PD_SESSION__PD_SESSION_H_
-#define _INCLUDE__PD_SESSION__PD_SESSION_H_
-
-#include <thread/capability.h>
-#include <parent/capability.h>
-#include <session/session.h>
-
-namespace Genode {
-
-	struct Pd_session : Session
-	{
-		static const char *service_name() { return "PD"; }
-
-		virtual ~Pd_session() { }
-
-		/**
-		 * Bind thread to protection domain
-		 *
-		 * \param thread  capability of thread to bind
-		 *
-		 * \return        0 on success or negative error code
-		 *
-		 * After successful bind, the thread will execute inside this
-		 * protection domain when started.
-		 */
-		virtual int bind_thread(Thread_capability thread) = 0;
-
-		/**
-		 * Assign parent to protection domain
-		 *
-		 * \param   parent  capability of parent interface
-		 * \return  0 on success, or negative error code
-		 */
-		virtual int assign_parent(Parent_capability parent) = 0;
-
-
-		/**
-		 * Assign PCI device to a protection domain.
-		 *
-		 * \param   pci_config_space  virtual address of the 4K PCI config
-		 *                            space extended memory of the device
-		 * \param   bdf               bus/device/function of the PCI device
-		 * \return  true              on success, or false in case of an error
-		 */
-		virtual bool assign_pci(addr_t pci_config_space, uint16_t bdf) = 0;
-
-		/*********************
-		 ** RPC declaration **
-		 *********************/
-
-		GENODE_RPC(Rpc_bind_thread,   int, bind_thread,   Thread_capability);
-		GENODE_RPC(Rpc_assign_parent, int, assign_parent, Parent_capability);
-		GENODE_RPC(Rpc_assign_pci, bool, assign_pci, addr_t, uint16_t);
-
-		GENODE_RPC_INTERFACE(Rpc_bind_thread, Rpc_assign_parent,
-		                     Rpc_assign_pci);
-	};
-}
-
-#endif /* _INCLUDE__PD_SESSION__PD_SESSION_H_ */
diff --git a/repos/base-nova/include/signal_session/nova_source.h b/repos/base-nova/include/signal_session/nova_source.h
deleted file mode 100644
index 8ba79f8a5c..0000000000
--- a/repos/base-nova/include/signal_session/nova_source.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * \brief  NOVA-specific signal source RPC interface
- * \author Norman Feske
- * \date   2011-04-12
- */
-
-/*
- * Copyright (C) 2011-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 _INCLUDE__SIGNAL_SESSION__NOVA_SOURCE_H_
-#define _INCLUDE__SIGNAL_SESSION__NOVA_SOURCE_H_
-
-#include <base/rpc.h>
-#include <signal_session/source.h>
-
-namespace Genode {
-
-	struct Nova_signal_source : Signal_source
-	{
-		/*********************
-		 ** RPC declaration **
-		 *********************/
-
-		GENODE_RPC(Rpc_register_semaphore, void, _register_semaphore,
-		           Native_capability const &);
-
-		GENODE_RPC_INTERFACE_INHERIT(Signal_source, Rpc_register_semaphore);
-	};
-}
-
-#endif /* _INCLUDE__SIGNAL_SESSION__NOVA_SOURCE_H_ */
diff --git a/repos/base-nova/include/signal_session/source_rpc_object.h b/repos/base-nova/include/signal_session/source_rpc_object.h
deleted file mode 100644
index 39aeacf846..0000000000
--- a/repos/base-nova/include/signal_session/source_rpc_object.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * \brief  Signal-source server interface
- * \author Norman Feske
- * \date   2010-02-03
- *
- * This file is only included by 'signal_session/server.h' and relies on the
- * headers included there. No include guards are needed. It is a separate
- * header file to make it easily replaceable by a platform-specific
- * implementation.
- */
-
-/*
- * Copyright (C) 2010-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.
- */
-
-#ifndef _INCLUDE__SIGNAL_SESSION__SOURCE_SERVER_H_
-#define _INCLUDE__SIGNAL_SESSION__SOURCE_SERVER_H_
-
-#include <base/rpc_server.h>
-#include <signal_session/nova_source.h>
-
-namespace Genode { struct Signal_source_rpc_object; }
-
-struct Genode::Signal_source_rpc_object : Rpc_object<Nova_signal_source,
-                                                     Signal_source_rpc_object>
-{
-	public:
-
-		Native_capability _blocking_semaphore;
-
-	public:
-
-		void _register_semaphore(Native_capability const &cap)
-		{
-			if (_blocking_semaphore.valid())
-				PWRN("overwritting blocking signal semaphore !!!");
-
-			_blocking_semaphore = cap;
-		}
-
-		Signal_source_rpc_object() {}
-};
-
-#endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_SERVER_H_ */
diff --git a/repos/base-nova/include/signal_session/source_client.h b/repos/base-nova/include/signal_source/client.h
similarity index 85%
rename from repos/base-nova/include/signal_session/source_client.h
rename to repos/base-nova/include/signal_source/client.h
index 8cd4aabfb0..13794da417 100644
--- a/repos/base-nova/include/signal_session/source_client.h
+++ b/repos/base-nova/include/signal_source/client.h
@@ -18,11 +18,11 @@
  * under the terms of the GNU General Public License version 2.
  */
 
-#ifndef _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_
-#define _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_
+#ifndef _INCLUDE__SIGNAL_SOURCE__CLIENT_H_
+#define _INCLUDE__SIGNAL_SOURCE__CLIENT_H_
 
 #include <base/rpc_client.h>
-#include <signal_session/nova_source.h>
+#include <signal_source/nova_signal_source.h>
 
 /* NOVA includes */
 #include <nova/syscalls.h>
@@ -60,9 +60,8 @@ namespace Genode {
 			/**
 			 * Constructor
 			 */
-			Signal_source_client(Signal_source_capability cap)
-			: Rpc_client<Nova_signal_source>(
-				static_cap_cast<Nova_signal_source>(cap))
+			Signal_source_client(Capability<Signal_source> cap)
+			: Rpc_client<Nova_signal_source>(static_cap_cast<Nova_signal_source>(cap))
 			{
 				/*
 				 * Make sure that we have acquired the
@@ -76,9 +75,9 @@ namespace Genode {
 			 ** Signal source interface **
 			 *****************************/
 
-			Signal wait_for_signal()
+			Signal wait_for_signal() override
 			{
-				/* 
+				/*
 				 * Block on semaphore, will be unblocked if
 				 * signal is available
 				 */
@@ -94,4 +93,4 @@ namespace Genode {
 	};
 }
 
-#endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_ */
+#endif /* _INCLUDE__SIGNAL_SOURCE__CLIENT_H_ */
diff --git a/repos/base-nova/include/signal_source/nova_signal_source.h b/repos/base-nova/include/signal_source/nova_signal_source.h
new file mode 100644
index 0000000000..5a2f221974
--- /dev/null
+++ b/repos/base-nova/include/signal_source/nova_signal_source.h
@@ -0,0 +1,30 @@
+/*
+ * \brief  NOVA-specific signal source RPC interface
+ * \author Norman Feske
+ * \date   2011-04-12
+ */
+
+/*
+ * Copyright (C) 2011-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 _INCLUDE__SIGNAL_SOURCE__NOVA_SIGNAL_SOURCE_H_
+#define _INCLUDE__SIGNAL_SOURCE__NOVA_SIGNAL_SOURCE_H_
+
+#include <base/rpc.h>
+#include <signal_source/signal_source.h>
+
+namespace Genode { struct Nova_signal_source; }
+
+struct Genode::Nova_signal_source : Signal_source
+{
+	GENODE_RPC(Rpc_register_semaphore, void, register_semaphore,
+	           Native_capability const &);
+
+	GENODE_RPC_INTERFACE_INHERIT(Signal_source, Rpc_register_semaphore);
+};
+
+#endif /* _INCLUDE__SIGNAL_SOURCE__NOVA_SIGNAL_SOURCE_H_ */
diff --git a/repos/base-nova/src/base/signal/platform.cc b/repos/base-nova/src/base/signal/platform.cc
index 23063d0e25..668615ff05 100644
--- a/repos/base-nova/src/base/signal/platform.cc
+++ b/repos/base-nova/src/base/signal/platform.cc
@@ -13,13 +13,12 @@
 
 
 /* Genode includes */
-#include <signal_session/connection.h>
+#include <base/signal.h>
+#include <base/trace/events.h>
 
 using namespace Genode;
 
-/************************
- ** Signal transmitter **
- ************************/
+
 void Signal_transmitter::submit(unsigned cnt)
 {
 	{
diff --git a/repos/base-nova/src/core/include/pd_session_component.h b/repos/base-nova/src/core/include/pd_session_component.h
deleted file mode 100644
index 57fb318b9a..0000000000
--- a/repos/base-nova/src/core/include/pd_session_component.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * \brief  Core-specific instance of the PD session interface
- * \author Christian Helmuth
- * \date   2006-07-17
- */
-
-/*
- * 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.
- */
-
-#ifndef _CORE__INCLUDE__PD_SESSION_COMPONENT_H_
-#define _CORE__INCLUDE__PD_SESSION_COMPONENT_H_
-
-/* Genode includes */
-#include <base/rpc_server.h>
-#include <util/arg_string.h>
-#include <pd_session/pd_session.h>
-
-/* core includes */
-#include <platform_pd.h>
-
-namespace Genode {
-
-	class Pd_session_component : public Rpc_object<Pd_session>
-	{
-		private:
-
-			/**
-			 * Read and store the PD label
-			 */
-			struct Label {
-
-				enum { MAX_LEN = 64 };
-				char string[MAX_LEN];
-
-				/**
-				 * Constructor
-				 */
-				Label(char const *args)
-				{
-					Arg_string::find_arg(args, "label").string(string, sizeof(string), "");
-				}
-
-			} const _label;
-
-			Platform_pd        _pd;
-			Parent_capability  _parent;
-			Rpc_entrypoint    *_thread_ep;
-
-		public:
-
-			Pd_session_component(Rpc_entrypoint *thread_ep,
-			                     Allocator * md_alloc, char const *args)
-			: _label(args),
-			  _pd(md_alloc, _label.string),
-			  _thread_ep(thread_ep) { }
-
-			/**
-			 * Register quota donation at allocator guard
-			 */
-			void upgrade_ram_quota(size_t ram_quota) { }
-
-
-			/**************************/
-			/** PD session interface **/
-			/**************************/
-
-			int bind_thread(Thread_capability);
-			int assign_parent(Parent_capability);
-			bool assign_pci(addr_t, uint16_t);
-	};
-}
-
-#endif /* _CORE__INCLUDE__PD_SESSION_COMPONENT_H_ */
diff --git a/repos/base-nova/src/core/include/signal_broker.h b/repos/base-nova/src/core/include/signal_broker.h
new file mode 100644
index 0000000000..8b6d0ecd57
--- /dev/null
+++ b/repos/base-nova/src/core/include/signal_broker.h
@@ -0,0 +1,135 @@
+/*
+ * \brief  NOVA-specific signal-delivery mechanism
+ * \author Norman Feske
+ * \date   2016-01-04
+ */
+
+/*
+ * Copyright (C) 2016 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__SIGNAL_BROKER_H_
+#define _CORE__INCLUDE__SIGNAL_BROKER_H_
+
+/* Genode includes */
+#include <base/tslab.h>
+
+/* core-local includes */
+#include <signal_source_component.h>
+#include <signal_source/capability.h>
+
+namespace Genode { class Signal_broker; }
+
+
+class Genode::Signal_broker
+{
+	private:
+
+		Allocator                            &_md_alloc;
+		Rpc_entrypoint                       &_source_ep;
+		Object_pool<Signal_context_component> _obj_pool;
+		Rpc_entrypoint                       &_context_ep;
+		Signal_source_component               _source;
+		Signal_source_capability              _source_cap;
+		Tslab<Signal_context_component,
+		      960*sizeof(long)>               _contexts_slab { &_md_alloc };
+
+	public:
+
+		class Invalid_signal_source : public Exception { };
+
+		Signal_broker(Allocator      &md_alloc,
+		              Rpc_entrypoint &source_ep,
+		              Rpc_entrypoint &context_ep)
+		:
+			_md_alloc(md_alloc),
+			_source_ep(source_ep),
+			_context_ep(context_ep),
+			_source(&_context_ep),
+			_source_cap(_source_ep.manage(&_source))
+		{ }
+
+		~Signal_broker()
+		{
+			/* remove source from entrypoint */
+			_source_ep.dissolve(&_source);
+
+			/* free all signal contexts */
+			while (Signal_context_component *r = _contexts_slab.first_object())
+				free_context(reinterpret_cap_cast<Signal_context>(r->cap()));
+		}
+
+		Signal_source_capability alloc_signal_source() { return _source_cap; }
+
+		void free_signal_source(Signal_source_capability) { }
+
+		/*
+		 * \throw Allocator::Out_of_memory
+		 */
+		Signal_context_capability
+		alloc_context(Signal_source_capability, unsigned long imprint)
+		{
+			/*
+			 * XXX  For now, we ignore the signal-source argument as we
+			 *      create only a single receiver for each PD.
+			 */
+
+			Native_capability sm = _source.blocking_semaphore();
+
+			if (!sm.valid()) {
+				PWRN("signal receiver sm is not valid");
+				for (;;);
+				return Signal_context_capability();
+			}
+
+			Native_capability si(cap_map()->insert());
+			Signal_context_capability cap = reinterpret_cap_cast<Signal_context>(si);
+
+			uint8_t res = Nova::create_si(cap.local_name(), __core_pd_sel, imprint,
+			                              sm.local_name());
+			if (res != Nova::NOVA_OK) {
+				PWRN("creating signal failed - error %u", res);
+				return Signal_context_capability();
+			}
+
+			/* the _contexts_slab may throw Allocator::Out_of_memory */
+			_obj_pool.insert(new (&_contexts_slab) Signal_context_component(cap));
+
+			/* return unique capability for the signal context */
+			return cap;
+		}
+
+		void free_context(Signal_context_capability context_cap)
+		{
+			Signal_context_component *context;
+			auto lambda = [&] (Signal_context_component *c) {
+				context = c;
+				if (context) _obj_pool.remove(context);
+			};
+			_obj_pool.apply(context_cap, lambda);
+
+			if (!context) {
+				PWRN("%p - specified signal-context capability has wrong type %lx",
+					 this, context_cap.local_name());
+				return;
+			}
+			destroy(&_contexts_slab, context);
+
+			Nova::revoke(Nova::Obj_crd(context_cap.local_name(), 0));
+			cap_map()->remove(context_cap.local_name(), 0);
+		}
+
+		void submit(Signal_context_capability cap, unsigned cnt)
+		{
+			/*
+			 * On NOVA, signals are submitted directly to the kernel, not
+			 * by using core as a proxy.
+			 */
+			ASSERT_NEVER_CALLED;
+		}
+};
+
+#endif /* _CORE__INCLUDE__SIGNAL_BROKER_H_ */
diff --git a/repos/base-nova/src/core/include/signal_session_component.h b/repos/base-nova/src/core/include/signal_session_component.h
deleted file mode 100644
index dfb201ee05..0000000000
--- a/repos/base-nova/src/core/include/signal_session_component.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * \brief  Signal service
- * \author Norman Feske
- * \date   2009-08-05
- */
-
-/*
- * 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.
- */
-
-#ifndef _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_
-#define _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_
-
-#include <signal_session/signal_session.h>
-#include <signal_session/source_rpc_object.h>
-#include <base/allocator_guard.h>
-#include <base/tslab.h>
-#include <base/lock.h>
-#include <base/rpc_client.h>
-#include <base/rpc_server.h>
-#include <util/fifo.h>
-#include <base/signal.h>
-
-namespace Genode {
-
-	class Signal_source_component;
-	class Signal_context_component;
-
-	typedef Fifo<Signal_context_component> Signal_queue;
-
-	class Signal_context_component : public Object_pool<Signal_context_component>::Entry
-	{
-		public:
-
-			/**
-			 * Constructor
-			 */
-			Signal_context_component(Signal_context_capability cap)
-			: Object_pool<Signal_context_component>::Entry(cap) { }
-	};
-
-
-	class Signal_source_component : public Signal_source_rpc_object
-	{
-		public:
-
-			/**
-			 * Constructor
-			 */
-			Signal_source_component(Rpc_entrypoint *) { }
-
-			/*****************************
-			 ** Signal-source interface **
-			 *****************************/
-
-			Signal wait_for_signal() { return Signal(0, 0); }
-	};
-
-
-	class Signal_session_component : public Rpc_object<Signal_session>
-	{
-		private:
-
-			Rpc_entrypoint                       *_source_ep;
-			Object_pool<Signal_context_component> _signal_queue;
-			Signal_source_component               _source;
-			Signal_source_capability              _source_cap;
-			Allocator_guard                       _md_alloc;
-			Tslab<Signal_context_component,
-			      960*sizeof(long)>               _contexts_slab;
-			Ipc_ostream                          *_ipc_ostream;
-
-		public:
-
-			/**
-			 * Constructor
-			 *
-			 * \param source_ep    entrypoint holding signal-source component
-			 *                     objects
-			 * \param context_ep   global pool of all signal contexts
-			 * \param md_alloc     backing-store allocator for
-			 *                     signal-context component objects
-			 *
-			 * To maintain proper synchronization, 'signal_source_ep' must be
-			 * the same entrypoint as used for the signal-session component.
-			 * The 'signal_context_ep' is only used for associative array
-			 * to map signal-context capabilities to 'Signal_context_component'
-			 * objects and as capability allocator for such objects.
-			 */
-			Signal_session_component(Rpc_entrypoint *source_ep,
-			                         Rpc_entrypoint *context_ep,
-			                         Allocator      *context_md_alloc,
-			                         size_t          ram_quota);
-
-			~Signal_session_component();
-
-			/**
-			 * Register quota donation at allocator guard
-			 */
-			void upgrade_ram_quota(size_t ram_quota) { _md_alloc.upgrade(ram_quota); }
-
-
-			/******************************
-			 ** Signal-session interface **
-			 ******************************/
-
-			Signal_source_capability signal_source();
-			Signal_context_capability alloc_context(long imprint);
-			void free_context(Signal_context_capability context_cap);
-			void submit(Signal_context_capability context_cap, unsigned cnt);
-
-
-			/**************************
-			 ** Rpc_object interface **
-			 **************************/
-
-			Rpc_exception_code dispatch(int opcode, Ipc_istream &is, Ipc_ostream &os)
-			{
-				/*
-				 * Make IPC output stream available to the submit function. The
-				 * stream is used to carry signal payload for the out-of-order
-				 * handling of 'wait_for_signal' replies.
-				 */
-				_ipc_ostream = &os;
-
-				/* dispatch RPC */
-				return Rpc_object<Signal_session>::dispatch(opcode, is, os);
-			}
-	};
-}
-
-#endif /* _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_ */
diff --git a/repos/base-nova/src/core/include/signal_source_component.h b/repos/base-nova/src/core/include/signal_source_component.h
new file mode 100644
index 0000000000..d284ca658f
--- /dev/null
+++ b/repos/base-nova/src/core/include/signal_source_component.h
@@ -0,0 +1,63 @@
+/*
+ * \brief  Signal-delivery mechanism
+ * \author Norman Feske
+ * \date   2009-08-05
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_
+#define _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_
+
+#include <base/object_pool.h>
+#include <signal_source/nova_signal_source.h>
+#include <assertion.h>
+
+namespace Genode {
+
+	class Signal_context_component;
+	class Signal_source_component;
+}
+
+
+struct Genode::Signal_context_component : Object_pool<Signal_context_component>::Entry
+{
+	Signal_context_component(Signal_context_capability cap)
+	: Object_pool<Signal_context_component>::Entry(cap) { }
+
+	Signal_source_component *source() { ASSERT_NEVER_CALLED; }
+};
+
+
+class Genode::Signal_source_component : public Rpc_object<Nova_signal_source,
+                                                          Signal_source_component>
+{
+	private:
+
+		Native_capability _blocking_semaphore;
+
+	public:
+
+		Signal_source_component(Rpc_entrypoint *) { }
+
+		void register_semaphore(Native_capability const &cap)
+		{
+			if (_blocking_semaphore.valid())
+				PWRN("overwritting blocking signal semaphore !!!");
+
+			_blocking_semaphore = cap;
+		}
+
+		Native_capability blocking_semaphore() const { return _blocking_semaphore; }
+
+		Signal wait_for_signal() { /* unused on NOVA */ return Signal(0, 0); }
+
+		void submit(Signal_context_component *, unsigned long) { /* unused on NOVA */ }
+};
+
+#endif /* _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_ */
diff --git a/repos/base-nova/src/core/pd_session_extension.cc b/repos/base-nova/src/core/pd_assign_pci.cc
similarity index 100%
rename from repos/base-nova/src/core/pd_session_extension.cc
rename to repos/base-nova/src/core/pd_assign_pci.cc
diff --git a/repos/base-nova/src/core/signal_session_component.cc b/repos/base-nova/src/core/signal_session_component.cc
deleted file mode 100644
index 9883e854c8..0000000000
--- a/repos/base-nova/src/core/signal_session_component.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * \brief  Implementation of the SIGNAL interface
- * \author Alexander Boettcher
- * \date   2015-03-04
- */
-
-/*
- * Copyright (C) 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.
- */
-
-/* Genode includes */
-#include <base/printf.h>
-
-/* core includes */
-#include <signal_session_component.h>
-
-using namespace Genode;
-
-
-/******************************
- ** Signal-session component **
- ******************************/
-
-Signal_session_component::Signal_session_component(Rpc_entrypoint *source_ep,
-                                                   Rpc_entrypoint *context_ep,
-                                                   Allocator      *context_md_alloc,
-                                                   size_t          ram_quota)
-:
-	_source_ep(source_ep),
-	_source(source_ep),
-	_source_cap(_source_ep->manage(&_source)),
-	_md_alloc(context_md_alloc, ram_quota),
-	_contexts_slab(&_md_alloc)
-{ }
-
-
-Signal_session_component::~Signal_session_component()
-{
-	/* remove _signal_source from entrypoint */
-	_source_ep->dissolve(&_source);
-
-	/* free all signal contexts */
-	while (Signal_context_component *r = _contexts_slab.first_object())
-		free_context(reinterpret_cap_cast<Signal_context>(Native_capability(r->cap())));
-}
-
-
-Signal_source_capability Signal_session_component::signal_source()
-{
-	return _source_cap;
-}
-
-extern "C" Genode::addr_t __core_pd_sel;
-
-Signal_context_capability Signal_session_component::alloc_context(long imprint)
-{
-	Native_capability sm = _source._blocking_semaphore;
-
-	if (!sm.valid()) {
-		PWRN("signal receiver sm is not valid");
-		return Signal_context_capability();
-	}
-
-	Native_capability si(cap_map()->insert());
-	Signal_context_capability cap = reinterpret_cap_cast<Signal_context>(si);
-
-	uint8_t res = Nova::create_si(cap.local_name(), __core_pd_sel, imprint,
-	                              sm.local_name());
-	if (res != Nova::NOVA_OK) {
-		PWRN("creating signal failed - error %u", res);
-		return Signal_context_capability();
-	}
-
-	try {
-		_signal_queue.insert(new (&_contexts_slab) Signal_context_component(cap));
-	} catch (Allocator::Out_of_memory) {
-		throw Out_of_metadata();
-	}
-
-	/* return unique capability for the signal context */
-	return cap;
-}
-
-
-void Signal_session_component::free_context(Signal_context_capability context_cap)
-{
-	Signal_context_component *context;
-	auto lambda = [&] (Signal_context_component *c) {
-		context = c;
-		if (context) _signal_queue.remove(context);
-	};
-	_signal_queue.apply(context_cap, lambda);
-
-	if (!context) {
-		PWRN("%p - specified signal-context capability has wrong type %lx",
-			 this, context_cap.local_name());
-		return;
-	}
-	destroy(&_contexts_slab, context);
-
-	Nova::revoke(Nova::Obj_crd(context_cap.local_name(), 0));
-	cap_map()->remove(context_cap.local_name(), 0);
-}
-
-
-void Signal_session_component::submit(Signal_context_capability context_cap,
-                                      unsigned                  cnt)
-{
-	PDBG("should not be called");
-}
diff --git a/repos/base-nova/src/core/target.inc b/repos/base-nova/src/core/target.inc
index ea82231e64..4cd6a29c55 100644
--- a/repos/base-nova/src/core/target.inc
+++ b/repos/base-nova/src/core/target.inc
@@ -21,7 +21,8 @@ SRC_CC       = context_area.cc \
                main.cc \
                pager.cc \
                pd_session_component.cc \
-               pd_session_extension.cc \
+               pd_upgrade_ram_quota.cc \
+               pd_assign_pci.cc \
                platform.cc \
                platform_pd.cc \
                platform_services.cc \
@@ -31,7 +32,6 @@ SRC_CC       = context_area.cc \
                rm_session_component.cc \
                rm_session_support.cc \
                rom_session_component.cc \
-               signal_session_component.cc \
                thread_start.cc \
                bios_data_area.cc \
                trace_session_component.cc
@@ -49,6 +49,7 @@ vpath ram_session_component.cc     $(GEN_CORE_DIR)
 vpath rom_session_component.cc     $(GEN_CORE_DIR)
 vpath cpu_session_component.cc     $(GEN_CORE_DIR)
 vpath pd_session_component.cc      $(GEN_CORE_DIR)
+vpath pd_upgrade_ram_quota.cc      $(GEN_CORE_DIR)
 vpath rm_session_component.cc      $(GEN_CORE_DIR)
 vpath trace_session_component.cc   $(GEN_CORE_DIR)
 vpath io_port_session_component.cc $(GEN_CORE_DIR)/spec/x86
diff --git a/repos/base-okl4/src/core/include/pd_session_component.h b/repos/base-okl4/src/core/include/pd_session_component.h
index 574bb9d13c..2bb4d3b958 100644
--- a/repos/base-okl4/src/core/include/pd_session_component.h
+++ b/repos/base-okl4/src/core/include/pd_session_component.h
@@ -21,45 +21,71 @@
 
 /* core includes */
 #include <platform.h>
+#include <signal_broker.h>
 
-namespace Genode {
-
-	class Pd_session_component : public Rpc_object<Okl4_pd_session>
-	{
-		private:
-
-			Platform_pd     _pd;
-			Rpc_entrypoint *_thread_ep;
-
-		public:
-
-			Pd_session_component(Rpc_entrypoint *thread_ep,
-			                     Allocator *md_alloc, const char *args)
-			: _thread_ep(thread_ep) { }
-
-			/**
-			 * Register quota donation at allocator guard
-			 */
-			void upgrade_ram_quota(size_t ram_quota) { }
+namespace Genode { class Pd_session_component; }
 
 
-			/**************************
-			 ** Pd session interface **
-			 **************************/
+class Genode::Pd_session_component : public Rpc_object<Okl4_pd_session>
+{
+	private:
 
-			int bind_thread(Thread_capability);
-			int assign_parent(Parent_capability);
+		Platform_pd     _pd;
+		Rpc_entrypoint &_thread_ep;
+		Signal_broker   _signal_broker;
+
+	public:
+
+		Pd_session_component(Rpc_entrypoint &thread_ep,
+		                     Rpc_entrypoint &receiver_ep,
+		                     Rpc_entrypoint &context_ep,
+		                     Allocator &md_alloc, const char *args)
+		:
+			_thread_ep(thread_ep),
+			_signal_broker(md_alloc, receiver_ep, context_ep)
+		{ }
+
+		/**
+		 * Register quota donation at allocator guard
+		 */
+		void upgrade_ram_quota(size_t ram_quota) { }
 
 
-			/*****************************
-			 ** OKL4-specific additions **
-			 *****************************/
+		/**************************
+		 ** Pd session interface **
+		 **************************/
 
-			void space_pager(Thread_capability thread);
+		int bind_thread(Thread_capability);
+		int assign_parent(Capability<Parent>);
+		bool assign_pci(addr_t, uint16_t) { return false; }
 
-			Okl4::L4_SpaceId_t space_id() {
-				return Okl4::L4_SpaceId(_pd.pd_id()); }
-	};
-}
+		Signal_source_capability alloc_signal_source() override {
+			return _signal_broker.alloc_signal_source(); }
+
+		void free_signal_source(Signal_source_capability cap) override {
+			_signal_broker.free_signal_source(cap); }
+
+		Signal_context_capability
+		alloc_context(Signal_source_capability sig_rec_cap, unsigned long imprint) override
+		{
+			return _signal_broker.alloc_context(sig_rec_cap, imprint);
+		}
+
+		void free_context(Signal_context_capability cap) override {
+			_signal_broker.free_context(cap); }
+
+		void submit(Signal_context_capability cap, unsigned n) override {
+			_signal_broker.submit(cap, n); }
+
+
+		/*****************************
+		 ** OKL4-specific additions **
+		 *****************************/
+
+		void space_pager(Thread_capability thread);
+
+		Okl4::L4_SpaceId_t space_id() {
+			return Okl4::L4_SpaceId(_pd.pd_id()); }
+};
 
 #endif /* _CORE__INCLUDE__OKL4__PD_SESSION_COMPONENT_H_ */
diff --git a/repos/base-okl4/src/core/okl4_pd_session_component.cc b/repos/base-okl4/src/core/okl4_pd_session_component.cc
index 73b53c4712..7a8e8a7c8b 100644
--- a/repos/base-okl4/src/core/okl4_pd_session_component.cc
+++ b/repos/base-okl4/src/core/okl4_pd_session_component.cc
@@ -21,7 +21,7 @@ using namespace Genode;
 
 void Pd_session_component::space_pager(Thread_capability thread)
 {
-	_thread_ep->apply(thread, [this] (Cpu_thread_component *cpu_thread)
+	_thread_ep.apply(thread, [this] (Cpu_thread_component *cpu_thread)
 	{
 		if (!cpu_thread) return;
 		_pd.space_pager(cpu_thread->platform_thread());
diff --git a/repos/base-okl4/src/core/target.inc b/repos/base-okl4/src/core/target.inc
index 1397fc271c..72d49c16d1 100644
--- a/repos/base-okl4/src/core/target.inc
+++ b/repos/base-okl4/src/core/target.inc
@@ -31,7 +31,6 @@ SRC_CC += cap_session_component.cc \
           rm_session_component.cc \
           rm_session_support.cc \
           rom_session_component.cc \
-          signal_session_component.cc \
           signal_source_component.cc \
           thread_start.cc \
           trace_session_component.cc
@@ -53,7 +52,6 @@ vpath pd_session_component.cc     $(GEN_CORE_DIR)
 vpath rm_session_component.cc     $(GEN_CORE_DIR)
 vpath io_mem_session_component.cc $(GEN_CORE_DIR)
 vpath io_mem_session_support.cc   $(GEN_CORE_DIR)
-vpath signal_session_component.cc $(GEN_CORE_DIR)
 vpath signal_source_component.cc  $(GEN_CORE_DIR)
 vpath trace_session_component.cc  $(GEN_CORE_DIR)
 vpath dataspace_component.cc      $(GEN_CORE_DIR)
diff --git a/repos/base-pistachio/src/core/target.inc b/repos/base-pistachio/src/core/target.inc
index ed9ebf03f0..febf051047 100644
--- a/repos/base-pistachio/src/core/target.inc
+++ b/repos/base-pistachio/src/core/target.inc
@@ -18,6 +18,8 @@ SRC_CC       = cap_session_component.cc \
                main.cc \
                multiboot_info.cc \
                pd_session_component.cc \
+               pd_assign_pci.cc \
+               pd_upgrade_ram_quota.cc \
                pager.cc \
                pager_ep.cc \
                pager_object.cc \
@@ -30,7 +32,6 @@ SRC_CC       = cap_session_component.cc \
                rm_session_component.cc \
                rm_session_support.cc \
                rom_session_component.cc \
-               signal_session_component.cc \
                signal_source_component.cc \
                thread_start.cc \
                trace_session_component.cc
@@ -48,10 +49,11 @@ vpath rom_session_component.cc    $(GEN_CORE_DIR)
 vpath cap_session_component.cc    $(GEN_CORE_DIR)
 vpath cpu_session_component.cc    $(GEN_CORE_DIR)
 vpath pd_session_component.cc     $(GEN_CORE_DIR)
+vpath pd_assign_pci.cc            $(GEN_CORE_DIR)
+vpath pd_upgrade_ram_quota.cc     $(GEN_CORE_DIR)
 vpath rm_session_component.cc     $(GEN_CORE_DIR)
 vpath io_mem_session_component.cc $(GEN_CORE_DIR)
 vpath io_mem_session_support.cc   $(GEN_CORE_DIR)
-vpath signal_session_component.cc $(GEN_CORE_DIR)
 vpath signal_source_component.cc  $(GEN_CORE_DIR)
 vpath trace_session_component.cc  $(GEN_CORE_DIR)
 vpath dataspace_component.cc      $(GEN_CORE_DIR)
diff --git a/repos/base-sel4/lib/mk/core.mk b/repos/base-sel4/lib/mk/core.mk
index 9d22dcb02d..9726f6a38d 100644
--- a/repos/base-sel4/lib/mk/core.mk
+++ b/repos/base-sel4/lib/mk/core.mk
@@ -11,6 +11,8 @@ SRC_CC      += \
                cpu_session_component.cc \
                cpu_session_support.cc \
                pd_session_component.cc \
+               pd_assign_pci.cc \
+               pd_upgrade_ram_quota.cc \
                io_mem_session_component.cc \
                io_mem_session_support.cc \
                thread_start.cc \
@@ -22,7 +24,6 @@ SRC_CC      += \
                rm_session_component.cc \
                rm_session_support.cc \
                irq_session_component.cc \
-               signal_session_component.cc \
                signal_source_component.cc \
                trace_session_component.cc \
                core_rm_session.cc \
@@ -47,11 +48,12 @@ vpath ram_session_component.cc    $(GEN_CORE_DIR)
 vpath rom_session_component.cc    $(GEN_CORE_DIR)
 vpath cpu_session_component.cc    $(GEN_CORE_DIR)
 vpath pd_session_component.cc     $(GEN_CORE_DIR)
+vpath pd_assign_pci.cc            $(GEN_CORE_DIR)
+vpath pd_upgrade_ram_quota.cc     $(GEN_CORE_DIR)
 vpath rm_session_component.cc     $(GEN_CORE_DIR)
 vpath io_mem_session_component.cc $(GEN_CORE_DIR)
 vpath io_mem_session_support.cc   $(GEN_CORE_DIR)
 vpath platform_services.cc        $(GEN_CORE_DIR)
-vpath signal_session_component.cc $(GEN_CORE_DIR)
 vpath signal_source_component.cc  $(GEN_CORE_DIR)
 vpath trace_session_component.cc  $(GEN_CORE_DIR)
 vpath dataspace_component.cc      $(GEN_CORE_DIR)
diff --git a/repos/base/include/base/env.h b/repos/base/include/base/env.h
index 29c9f201b8..2af7ef55c5 100644
--- a/repos/base/include/base/env.h
+++ b/repos/base/include/base/env.h
@@ -21,7 +21,8 @@
 #include <ram_session/ram_session.h>
 #include <cpu_session/cpu_session.h>
 #include <cpu_session/capability.h>
-#include <pd_session/pd_session.h>
+#include <pd_session/capability.h>
+#include <cap_session/cap_session.h>
 #include <base/allocator.h>
 #include <base/snprintf.h>
 #include <base/lock.h>
@@ -80,6 +81,7 @@ struct Genode::Env
 	 * PD session of the component as created by the parent
 	 */
 	virtual Pd_session *pd_session() = 0;
+	virtual Pd_session_capability pd_session_cap() = 0;
 
 	/**
 	 * Heap backed by the RAM session of the environment
@@ -116,6 +118,4 @@ struct Genode::Env
 
 };
 
-
-
 #endif /* _INCLUDE__BASE__ENV_H_ */
diff --git a/repos/base/include/base/rpc_server.h b/repos/base/include/base/rpc_server.h
index 02dfd1eea6..8db4b89691 100644
--- a/repos/base/include/base/rpc_server.h
+++ b/repos/base/include/base/rpc_server.h
@@ -385,16 +385,15 @@ class Genode::Rpc_entrypoint : Thread_base, public Object_pool<Rpc_object_base>
 		 *
 		 * \noapi
 		 *
-		 * Note: This is a temporary API method, which is going to be
-		 * removed. Please do not use this method.
-		 *
-		 * In combination with the 'reply_dst' accessor method, this
-		 * method can be used to implement services that dispatch client
-		 * requests out of order. In such cases, the server activation may
-		 * send reply messages to multiple blocking clients before
-		 * answering the original call.
+		 * In combination with the 'reply_dst' accessor method, this method
+		 * allows for the dispatching of client requests out of order. The only
+		 * designated user of this method is core's PD service. The
+		 * 'Pd_session::submit' RPC function uses it to send a reply to a
+		 * caller of the 'Signal_source::wait_for_signal' RPC function before
+		 * returning from the 'submit' call.
 		 */
-		void explicit_reply(Untyped_capability reply_cap, int return_value);
+		void reply_signal_info(Untyped_capability reply_cap,
+		                       unsigned long imprint, unsigned long cnt);
 
 		/**
 		 * Return true if the caller corresponds to the entrypoint called
diff --git a/repos/base/include/base/signal.h b/repos/base/include/base/signal.h
index 9f44d9211a..a8f2d769aa 100644
--- a/repos/base/include/base/signal.h
+++ b/repos/base/include/base/signal.h
@@ -20,7 +20,7 @@
 #include <util/noncopyable.h>
 #include <util/list.h>
 #include <base/semaphore.h>
-#include <signal_session/signal_session.h>
+#include <base/capability.h>
 
 /* only needed for base-hw */
 namespace Kernel { struct Signal_receiver; }
@@ -28,15 +28,18 @@ namespace Kernel { struct Signal_receiver; }
 namespace Genode {
 
 	class Signal_source;
+
 	class Signal_receiver;
 	class Signal_context;
 	class Signal_context_registry;
 	class Signal_transmitter;
 	class Signal;
 	class Signal_dispatcher_base;
-	class Signal_connection;
-	template <typename> class Signal_dispatcher;
-	Signal_connection * signal_connection();
+
+	template <typename>           class Signal_dispatcher;
+	template <typename, typename> class Signal_handler;
+
+	typedef Capability<Signal_context> Signal_context_capability;
 }
 
 
@@ -129,8 +132,6 @@ class Genode::Signal_transmitter
 
 		Signal_context_capability _context;  /* destination */
 
-		Signal_connection * connection();
-
 	public:
 
 		/**
@@ -179,7 +180,7 @@ class Genode::Signal_receiver : Noncopyable
 		 * Provides the kernel-object name via the 'dst' method. This is
 		 * needed for 'base-hw' only.
 		 */
-		Signal_receiver_capability _cap;
+		Capability<Signal_source> _cap;
 
 		/**
 		 * List of associated contexts
@@ -286,7 +287,7 @@ class Genode::Signal_receiver : Noncopyable
 		 * source associated with the process. It must not be used for other
 		 * purposes.
 		 */
-		static void dispatch_signals(Signal_source *signal_source);
+		static void dispatch_signals(Signal_source *);
 };
 
 
diff --git a/repos/base/include/pd_session/client.h b/repos/base/include/pd_session/client.h
index b81438d743..7fbc4deae9 100644
--- a/repos/base/include/pd_session/client.h
+++ b/repos/base/include/pd_session/client.h
@@ -28,18 +28,27 @@ struct Genode::Pd_session_client : Rpc_client<Pd_session>
 	int bind_thread(Thread_capability thread) override {
 		return call<Rpc_bind_thread>(thread); }
 
-	int assign_parent(Parent_capability parent) override {
+	int assign_parent(Capability<Parent> parent) override {
 		return call<Rpc_assign_parent>(parent); }
 
-	/**
-	 * Dummy stub for PCI-device assignment operation
-	 *
-	 * The assign_pci function exists only in the NOVA-specific version of the
-	 * PD-session interface. This empty dummy stub merely exists to maintain
-	 * API compatibility accross all base platforms so that drivers don't need
-	 * to distinguish NOVA from non-NOVA.
-	 */
-	bool assign_pci(addr_t) { return false; }
+	bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) override {
+		return call<Rpc_assign_pci>(pci_config_memory_address, bdf); }
+
+	Signal_source_capability alloc_signal_source() override {
+		return call<Rpc_alloc_signal_source>(); }
+
+	void free_signal_source(Signal_source_capability cap) override {
+		call<Rpc_free_signal_source>(cap); }
+
+	Signal_context_capability alloc_context(Signal_source_capability source,
+	                                        unsigned long imprint) override {
+		return call<Rpc_alloc_context>(source, imprint); }
+
+	void free_context(Signal_context_capability cap) override {
+		call<Rpc_free_context>(cap); }
+
+	void submit(Signal_context_capability receiver, unsigned cnt = 1) override {
+		call<Rpc_submit>(receiver, cnt); }
 };
 
 #endif /* _INCLUDE__PD_SESSION__CLIENT_H_ */
diff --git a/repos/base/include/pd_session/connection.h b/repos/base/include/pd_session/connection.h
index d1b4fa0bd2..c3b023622c 100644
--- a/repos/base/include/pd_session/connection.h
+++ b/repos/base/include/pd_session/connection.h
@@ -22,7 +22,7 @@ namespace Genode { struct Pd_connection; }
 
 struct Genode::Pd_connection : Connection<Pd_session>, Pd_session_client
 {
-	enum { RAM_QUOTA = 4*1024 };
+	enum { RAM_QUOTA = 4*1024*sizeof(long) };
 
 	/**
 	 * Constructor
diff --git a/repos/base/include/pd_session/pd_session.h b/repos/base/include/pd_session/pd_session.h
index 64ef234bad..a342bbcf46 100644
--- a/repos/base/include/pd_session/pd_session.h
+++ b/repos/base/include/pd_session/pd_session.h
@@ -1,6 +1,7 @@
 /*
  * \brief  Protection domain (PD) session interface
  * \author Christian Helmuth
+ * \author Norman Feske
  * \date   2006-06-27
  *
  * A pd session represents the protection domain of a program.
@@ -16,11 +17,17 @@
 #ifndef _INCLUDE__PD_SESSION__PD_SESSION_H_
 #define _INCLUDE__PD_SESSION__PD_SESSION_H_
 
+#include <base/exception.h>
 #include <thread/capability.h>
-#include <parent/capability.h>
 #include <session/session.h>
+#include <signal_source/signal_source.h>
 
-namespace Genode { struct Pd_session; }
+namespace Genode {
+
+	struct Pd_session;
+	struct Parent;
+	struct Signal_context;
+}
 
 
 struct Genode::Pd_session : Session
@@ -47,17 +54,117 @@ struct Genode::Pd_session : Session
 	 * \param   parent  capability of parent interface
 	 * \return  0 on success, or negative error code
 	 */
-	virtual int assign_parent(Parent_capability parent) = 0;
+	virtual int assign_parent(Capability<Parent> parent) = 0;
+
+	/**
+	 * Assign PCI device to PD
+	 *
+	 * The specified address has to refer to the locally mapped PCI
+	 * configuration space of the device.
+	 *
+	 * This function is solely used on the NOVA kernel.
+	 */
+	virtual bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) = 0;
+
+
+	/********************************
+	 ** Support for the signal API **
+	 ********************************/
+
+	typedef Capability<Signal_source> Signal_source_capability;
+
+	class Out_of_metadata       : public Exception { };
+	class Invalid_signal_source : public Exception { };
+
+	/**
+	 * Create a new signal source
+	 *
+	 * \return  a cap that acts as reference to the created source
+	 *
+	 * The signal source provides an interface to wait for incoming signals.
+	 *
+	 * \throw Out_of_metadata
+	 */
+	virtual Signal_source_capability alloc_signal_source() = 0;
+
+	/**
+	 * Free a signal source
+	 *
+	 * \param cap  capability of the signal source to destroy
+	 */
+	virtual void free_signal_source(Signal_source_capability cap) = 0;
+
+	/**
+	 * Allocate signal context
+	 *
+	 * \param source  signal source that shall provide the new context
+	 *
+	 *
+	 * \param imprint  opaque value that gets delivered with signals
+	 *                 originating from the allocated signal-context capability
+	 * \return new signal-context capability
+	 *
+	 * \throw Out_of_metadata
+	 * \throw Invalid_signal_source
+	 */
+	virtual Capability<Signal_context>
+	alloc_context(Signal_source_capability source, unsigned long imprint) = 0;
+
+	/**
+	 * Free signal-context
+	 *
+	 * \param cap  capability of signal-context to release
+	 */
+	virtual void free_context(Capability<Signal_context> cap) = 0;
+
+	/**
+	 * Submit signals to the specified signal context
+	 *
+	 * \param context  signal destination
+	 * \param cnt      number of signals to submit at once
+	 *
+	 * The 'context' argument does not necessarily belong to this PD session.
+	 * Normally, it is a capability obtained from a potentially untrusted
+	 * component. Because we cannot trust this capability, signals are not
+	 * submitted by invoking 'cap' directly but by using it as argument to our
+	 * trusted PD-session interface. Otherwise, a potential signal receiver
+	 * could supply a capability with a blocking interface to compromise the
+	 * nonblocking behaviour of the signal submission.
+	 */
+	virtual void submit(Capability<Signal_context> context, unsigned cnt = 1) = 0;
+
+
+	/***********************************
+	 ** Support for the RPC framework **
+	 ***********************************/
 
 
 	/*********************
 	 ** RPC declaration **
 	 *********************/
 
-	GENODE_RPC(Rpc_bind_thread,   int, bind_thread,   Thread_capability);
-	GENODE_RPC(Rpc_assign_parent, int, assign_parent, Parent_capability);
+	GENODE_RPC(Rpc_bind_thread,   int,  bind_thread,   Thread_capability);
+	GENODE_RPC(Rpc_assign_parent, int,  assign_parent, Capability<Parent>);
+	GENODE_RPC(Rpc_assign_pci,    bool, assign_pci,    addr_t, uint16_t);
 
-	GENODE_RPC_INTERFACE(Rpc_bind_thread, Rpc_assign_parent);
+	GENODE_RPC_THROW(Rpc_alloc_signal_source, Signal_source_capability,
+	                 alloc_signal_source, GENODE_TYPE_LIST(Out_of_metadata));
+
+	GENODE_RPC(Rpc_free_signal_source, void, free_signal_source, Signal_source_capability);
+
+	GENODE_RPC_THROW(Rpc_alloc_context, Capability<Signal_context>, alloc_context,
+	                 GENODE_TYPE_LIST(Out_of_metadata, Invalid_signal_source),
+	                 Signal_source_capability, unsigned long);
+
+	GENODE_RPC(Rpc_free_context, void, free_context,
+	           Capability<Signal_context>);
+
+	GENODE_RPC(Rpc_submit, void, submit, Capability<Signal_context>, unsigned);
+
+
+	GENODE_RPC_INTERFACE(Rpc_bind_thread, Rpc_assign_parent, Rpc_assign_pci,
+	                     Rpc_alloc_signal_source, Rpc_free_signal_source,
+	                     Rpc_alloc_context,  Rpc_free_context, Rpc_submit);
 };
 
 #endif /* _INCLUDE__PD_SESSION__PD_SESSION_H_ */
diff --git a/repos/base/include/signal_session/capability.h b/repos/base/include/signal_session/capability.h
deleted file mode 100644
index fc4e1d247c..0000000000
--- a/repos/base/include/signal_session/capability.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * \brief  Signal-session capability type
- * \author Norman Feske
- * \date   2009-08-05
- */
-
-/*
- * 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.
- */
-
-#ifndef _INCLUDE__SIGNAL_SESSION__CAPABILITY_H_
-#define _INCLUDE__SIGNAL_SESSION__CAPABILITY_H_
-
-#include <base/capability.h>
-#include <signal_session/signal_session.h>
-
-namespace Genode {
-
-	typedef Capability<Signal_session> Signal_session_capability;
-}
-
-#endif /* _INCLUDE__SIGNAL_SESSION__CAPABILITY_H_ */
diff --git a/repos/base/include/signal_session/client.h b/repos/base/include/signal_session/client.h
deleted file mode 100644
index 008fbc09fd..0000000000
--- a/repos/base/include/signal_session/client.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * \brief  Client-side signal session interface
- * \author Norman Feske
- * \date   2009-08-05
- */
-
-/*
- * 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.
- */
-
-#ifndef _INCLUDE__SIGNAL_SESSION__CLIENT_H_
-#define _INCLUDE__SIGNAL_SESSION__CLIENT_H_
-
-#include <signal_session/capability.h>
-#include <signal_session/signal_session.h>
-#include <base/rpc_client.h>
-#include <signal_session/source_client.h>
-
-namespace Genode { struct Signal_session_client; }
-
-
-struct Genode::Signal_session_client : Rpc_client<Signal_session>
-{
-	explicit Signal_session_client(Signal_session_capability session)
-	: Rpc_client<Signal_session>(session) { }
-
-	Signal_source_capability signal_source() override {
-		return call<Rpc_signal_source>(); }
-
-	Signal_context_capability alloc_context(long imprint) override {
-		return call<Rpc_alloc_context>(imprint); }
-
-	void free_context(Signal_context_capability cap) override {
-		call<Rpc_free_context>(cap); }
-
-	void submit(Signal_context_capability receiver, unsigned cnt = 1) override {
-		call<Rpc_submit>(receiver, cnt); }
-};
-
-#endif /* _INCLUDE__CAP_SESSION__CLIENT_H_ */
diff --git a/repos/base/include/signal_session/connection.h b/repos/base/include/signal_session/connection.h
deleted file mode 100644
index 984759a6ad..0000000000
--- a/repos/base/include/signal_session/connection.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * \brief  Connection to signal service
- * \author Norman Feske
- * \date   2009-08-05
- */
-
-/*
- * 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.
- */
-
-#ifndef _INCLUDE__SIGNAL_SESSION__CONNECTION_H_
-#define _INCLUDE__SIGNAL_SESSION__CONNECTION_H_
-
-#include <signal_session/client.h>
-#include <base/connection.h>
-
-namespace Genode { struct Signal_connection; }
-
-
-struct Genode::Signal_connection : Connection<Signal_session>, Signal_session_client
-{
-	Signal_connection()
-	:
-		Connection<Signal_session>(session("ram_quota=16K")),
-		Signal_session_client(cap())
-	{ }
-};
-
-#endif /* _INCLUDE__CAP_SESSION__CONNECTION_H_ */
diff --git a/repos/base/include/signal_session/signal_session.h b/repos/base/include/signal_session/signal_session.h
deleted file mode 100644
index ba9eb7026e..0000000000
--- a/repos/base/include/signal_session/signal_session.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * \brief  Signal session interface
- * \author Norman Feske
- * \date   2009-08-05
- */
-
-/*
- * 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.
- */
-
-#ifndef _INCLUDE__SIGNAL_SESSION__SIGNAL_SESSION_H_
-#define _INCLUDE__SIGNAL_SESSION__SIGNAL_SESSION_H_
-
-#include <base/capability.h>
-#include <base/exception.h>
-#include <signal_session/source.h>
-#include <session/session.h>
-
-namespace Genode {
-
-	class Signal_context;
-	class Signal_receiver;
-
-	typedef Capability<Signal_receiver> Signal_receiver_capability;
-	typedef Capability<Signal_context>  Signal_context_capability;
-	typedef Capability<Signal_source>   Signal_source_capability;
-
-	struct Signal_session;
-}
-
-
-struct Genode::Signal_session : Session
-{
-	static const char *service_name() { return "SIGNAL"; }
-
-	virtual ~Signal_session() { }
-
-	class Out_of_metadata : public Exception { };
-
-	/**
-	 * Request capability for the signal-source interface
-	 */
-	virtual Signal_source_capability signal_source() = 0;
-
-	/**
-	 * Allocate signal context
-	 *
-	 * \param imprint  opaque value that gets delivered with signals
-	 *                 originating from the allocated signal-context
-	 *                 capability
-	 * \return new signal-context capability
-	 * \throw  Out_of_metadata
-	 */
-	virtual Signal_context_capability alloc_context(long imprint) = 0;
-
-	/**
-	 * Free signal-context
-	 *
-	 * \param cap  capability of signal-context to release
-	 */
-	virtual void free_context(Signal_context_capability cap) = 0;
-
-	/**
-	 * Submit signals to the specified signal context
-	 *
-	 * \param context  signal destination
-	 * \param cnt      number of signals to submit at once
-	 *
-	 * Note that the 'context' argument does not necessarily belong to
-	 * the signal session. Normally, it is a capability obtained from
-	 * a potentially untrusted source. Because we cannot trust this
-	 * capability, signals are not submitted by invoking 'cap' directly
-	 * but by using it as argument to our trusted signal-session
-	 * interface. Otherwise, a potential signal receiver could supply
-	 * a capability with a blocking interface to compromise the
-	 * nonblocking behaviour of the signal submission.
-	 */
-	virtual void submit(Signal_context_capability context,
-	                    unsigned cnt = 1) = 0;
-
-
-	/*********************
-	 ** RPC declaration **
-	 *********************/
-
-	GENODE_RPC(Rpc_signal_source, Signal_source_capability, signal_source);
-	GENODE_RPC_THROW(Rpc_alloc_context, Signal_context_capability, alloc_context,
-	                 GENODE_TYPE_LIST(Out_of_metadata), long);
-	GENODE_RPC(Rpc_free_context, void, free_context, Signal_context_capability);
-	GENODE_RPC(Rpc_submit, void, submit, Signal_context_capability, unsigned);
-
-	GENODE_RPC_INTERFACE(Rpc_submit, Rpc_signal_source, Rpc_alloc_context,
-	                     Rpc_free_context);
-};
-
-#endif /* _INCLUDE__CAP_SESSION__CAP_SESSION_H_ */
diff --git a/repos/base/include/signal_session/source_client.h b/repos/base/include/signal_session/source_client.h
deleted file mode 100644
index afdcc1fa46..0000000000
--- a/repos/base/include/signal_session/source_client.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * \brief  Signal-source client interface
- * \author Norman Feske
- * \date   2010-02-03
- *
- * See documentation in 'signal_session/source.h'.
- */
-
-/*
- * 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.
- */
-
-#ifndef _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_
-#define _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_
-
-#include <signal_session/source.h>
-#include <base/rpc_client.h>
-
-namespace Genode { struct Signal_source_client; }
-
-
-struct Genode::Signal_source_client : Rpc_client<Signal_source>
-{
-	Signal_source_client(Signal_source_capability signal_source)
-	: Rpc_client<Signal_source>(signal_source) { }
-
-	Signal wait_for_signal() override { return call<Rpc_wait_for_signal>(); }
-};
-
-#endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_CLIENT_H_ */
diff --git a/repos/base/include/signal_source/capability.h b/repos/base/include/signal_source/capability.h
new file mode 100644
index 0000000000..7fcd489158
--- /dev/null
+++ b/repos/base/include/signal_source/capability.h
@@ -0,0 +1,22 @@
+/*
+ * \brief  Signal-source capability type
+ * \author Norman Feske
+ * \date   2016-01-04
+ */
+
+/*
+ * Copyright (C) 2016 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 _INCLUDE__SIGNAL_SOURCE__CAPABILITY_H_
+#define _INCLUDE__SIGNAL_SOURCE__CAPABILITY_H_
+
+#include <base/capability.h>
+#include <signal_source/signal_source.h>
+
+namespace Genode { typedef Capability<Signal_source> Signal_source_capability; }
+
+#endif /* _INCLUDE__SIGNAL_SOURCE__CAPABILITY_H_ */
diff --git a/repos/base/include/signal_source/client.h b/repos/base/include/signal_source/client.h
new file mode 100644
index 0000000000..aa24488987
--- /dev/null
+++ b/repos/base/include/signal_source/client.h
@@ -0,0 +1,30 @@
+/*
+ * \brief  Client-side signal-source interface
+ * \author Norman Feske
+ * \date   2016-01-04
+ */
+
+/*
+ * Copyright (C) 2016 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 _INCLUDE__SIGNAL_SOURCE__CLIENT_H_
+#define _INCLUDE__SIGNAL_SOURCE__CLIENT_H_
+
+#include <base/rpc_client.h>
+#include <pd_session/pd_session.h>
+
+namespace Genode { class Signal_source_client; }
+
+struct Genode::Signal_source_client : Rpc_client<Signal_source>
+{
+	Signal_source_client(Capability<Signal_source> signal_source)
+	: Rpc_client<Signal_source>(signal_source) { }
+
+	Signal wait_for_signal() override { return call<Rpc_wait_for_signal>(); }
+};
+
+#endif /* _INCLUDE__SIGNAL_SOURCE__CLIENT_H_ */
diff --git a/repos/base/include/signal_session/source_rpc_object.h b/repos/base/include/signal_source/rpc_object.h
similarity index 75%
rename from repos/base/include/signal_session/source_rpc_object.h
rename to repos/base/include/signal_source/rpc_object.h
index b60ff590d7..cacd128c10 100644
--- a/repos/base/include/signal_session/source_rpc_object.h
+++ b/repos/base/include/signal_source/rpc_object.h
@@ -15,14 +15,14 @@
  * under the terms of the GNU General Public License version 2.
  */
 
-#ifndef _INCLUDE__SIGNAL_SESSION__SOURCE_RPC_OBJECT_H_
-#define _INCLUDE__SIGNAL_SESSION__SOURCE_RPC_OBJECT_H_
+#ifndef _INCLUDE__SIGNAL_SOURCE__RPC_OBJECT_H_
+#define _INCLUDE__SIGNAL_SOURCE__RPC_OBJECT_H_
 
-#include <signal_session/source.h>
 #include <base/rpc_server.h>
+#include <signal_source/signal_source.h>
 
 namespace Genode { struct Signal_source_rpc_object; }
 
 struct Genode::Signal_source_rpc_object : Rpc_object<Signal_source> { };
 
-#endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_RPC_OBJECT_H_ */
+#endif /* _INCLUDE__SIGNAL_SOURCE__RPC_OBJECT_H_ */
diff --git a/repos/base/include/signal_session/source.h b/repos/base/include/signal_source/signal_source.h
similarity index 55%
rename from repos/base/include/signal_session/source.h
rename to repos/base/include/signal_source/signal_source.h
index 5e4574cf95..5dbc4e99be 100644
--- a/repos/base/include/signal_session/source.h
+++ b/repos/base/include/signal_source/signal_source.h
@@ -3,10 +3,9 @@
  * \author Norman Feske
  * \date   2010-02-03
  *
- * This file is only included by 'signal_session/signal_session.h' and relies
- * on the headers included there. No include guards are needed. It is a
- * separate header file to make it easily replaceable by a platform-specific
- * implementation.
+ * This file is only included by 'pd_session/pd_session.h' and relies
+ * on the headers included there. It is a separate header file to make it
+ * easily replaceable by a platform-specific implementation.
  */
 
 /*
@@ -16,22 +15,19 @@
  * under the terms of the GNU General Public License version 2.
  */
 
-#ifndef _INCLUDE__SIGNAL_SESSION__SOURCE_H_
-#define _INCLUDE__SIGNAL_SESSION__SOURCE_H_
-
-#include <base/rpc.h>
-
-namespace Genode { struct Signal_source; }
+#ifndef _INCLUDE__SIGNAL_SOURCE__SIGNAL_SOURCE_H_
+#define _INCLUDE__SIGNAL_SOURCE__SIGNAL_SOURCE_H_
 
+namespace Genode { class Signal_source; }
 
 /**
- * Blocking part of the signal-session interface
+ * Blocking part of the PD-session interface
  *
  * The blocking 'wait_for_signal()' operation cannot be part of the
- * signal-session interface because otherwise, context allocations or
+ * PD-session interface because otherwise, context allocations or
  * signal submissions would not be possible while blocking for signals.
- * Therefore, the blocking part is implemented a separate interface,
- * which can be used by an independent thread.
+ * Therefore, the blocking part is implemented as a kernel-specific
+ * special case.
  */
 struct Genode::Signal_source
 {
@@ -44,10 +40,7 @@ struct Genode::Signal_source
 
 		public:
 
-			Signal(long imprint, int num) :
-				_imprint(imprint),
-				_num(num)
-			{ }
+			Signal(long imprint, int num) : _imprint(imprint), _num(num) { }
 
 			Signal() : _imprint(0), _num(0) { }
 
@@ -72,4 +65,4 @@ struct Genode::Signal_source
 	GENODE_RPC_INTERFACE(Rpc_wait_for_signal);
 };
 
-#endif /* _INCLUDE__SIGNAL_SESSION__SOURCE_H_ */
+#endif /* _INCLUDE__SIGNAL_SOURCE__SIGNAL_SOURCE_H_ */
diff --git a/repos/base/src/base/env/platform_env.h b/repos/base/src/base/env/platform_env.h
index 867e06b4b9..f3ed2846b2 100644
--- a/repos/base/src/base/env/platform_env.h
+++ b/repos/base/src/base/env/platform_env.h
@@ -144,6 +144,7 @@ class Genode::Platform_env : public Genode::Env, public Emergency_ram_reserve
 		Cpu_session_capability  cpu_session_cap() { return  _resources.cpu; }
 		Rm_session             *rm_session()      { return &_resources.rm; }
 		Pd_session             *pd_session()      { return &_resources.pd; }
+		Pd_session_capability   pd_session_cap()  { return  _resources.pd; }
 		Allocator              *heap()            { return &_heap; }
 };
 
diff --git a/repos/base/src/base/server/common.cc b/repos/base/src/base/server/common.cc
index 4a7428ac3d..9042ccd054 100644
--- a/repos/base/src/base/server/common.cc
+++ b/repos/base/src/base/server/common.cc
@@ -49,7 +49,8 @@ void Rpc_entrypoint::omit_reply()
 }
 
 
-void Rpc_entrypoint::explicit_reply(Untyped_capability reply_cap, int return_value)
+void Rpc_entrypoint::reply_signal_info(Untyped_capability reply_cap,
+                                       unsigned long imprint, unsigned long cnt)
 {
 	if (!_ipc_server) return;
 
@@ -57,9 +58,9 @@ void Rpc_entrypoint::explicit_reply(Untyped_capability reply_cap, int return_val
 	Untyped_capability last_reply_cap = _ipc_server->dst();
 
 	/* direct ipc server to the specified reply destination */
-	_ipc_server->ret(return_value);
+	_ipc_server->ret(0);
 	_ipc_server->dst(reply_cap);
-	*_ipc_server << IPC_REPLY;
+	*_ipc_server << Signal_source::Signal(imprint, cnt) << IPC_REPLY;
 
 	/* restore reply capability of the original request */
 	_ipc_server->dst(last_reply_cap);
diff --git a/repos/base/src/base/signal/common.cc b/repos/base/src/base/signal/common.cc
index 446cc19106..29ad1b9f6d 100644
--- a/repos/base/src/base/signal/common.cc
+++ b/repos/base/src/base/signal/common.cc
@@ -14,20 +14,12 @@
  */
 
 /* Genode includes */
+#include <base/env.h>
 #include <base/signal.h>
-#include <signal_session/connection.h>
+#include <base/trace/events.h>
 
 using namespace Genode;
 
-/**
- * Return process-wide signal session
- */
-Signal_connection * Genode::signal_connection()
-{
-	static Signal_connection sc;
-	return &sc;
-}
-
 
 /************
  ** Signal **
@@ -110,9 +102,6 @@ Signal_context::~Signal_context()
  ** Signal_transmitter **
  ************************/
 
-Signal_connection * Signal_transmitter::connection() { return signal_connection(); }
-
-
 Signal_transmitter::Signal_transmitter(Signal_context_capability context)
 : _context(context) { }
 
@@ -201,7 +190,7 @@ void Signal_receiver::_unsynchronized_dissolve(Signal_context * const context)
 	_platform_begin_dissolve(context);
 
 	/* tell core to stop sending signals referring to the context */
-	signal_connection()->free_context(context->_cap);
+	env()->pd_session()->free_context(context->_cap);
 
 	/* restore default initialization of signal context */
 	context->_receiver = 0;
diff --git a/repos/base/src/base/signal/platform.cc b/repos/base/src/base/signal/platform.cc
index d175021f77..728cdf62a3 100644
--- a/repos/base/src/base/signal/platform.cc
+++ b/repos/base/src/base/signal/platform.cc
@@ -13,17 +13,20 @@
  */
 
 
-#include <signal_session/connection.h>
+#include <base/env.h>
+#include <base/trace/events.h>
 
 using namespace Genode;
 
+
 /************************
  ** Signal transmitter **
  ************************/
+
 void Signal_transmitter::submit(unsigned cnt)
 {
 	{
 		Trace::Signal_submit trace_event(cnt);
 	}
-	connection()->submit(_context, cnt);
+	env()->pd_session()->submit(_context, cnt);
 }
diff --git a/repos/base/src/base/signal/signal.cc b/repos/base/src/base/signal/signal.cc
index 22f41f3e31..2a8e11ec85 100644
--- a/repos/base/src/base/signal/signal.cc
+++ b/repos/base/src/base/signal/signal.cc
@@ -11,10 +11,12 @@
  * under the terms of the GNU General Public License version 2.
  */
 
+#include <util/retry.h>
+#include <base/env.h>
 #include <base/signal.h>
 #include <base/thread.h>
 #include <base/trace/events.h>
-#include <signal_session/connection.h>
+#include <signal_source/client.h>
 
 using namespace Genode;
 
@@ -63,7 +65,7 @@ class Signal_handler_thread : Thread<STACK_SIZE>, Lock
 
 Signal_source *Signal_handler_thread::signal_source()
 {
-	static Signal_source_client sigsrc(signal_connection()->signal_source());
+	static Signal_source_client sigsrc(env()->pd_session()->alloc_signal_source());
 	return &sigsrc;
 }
 
@@ -203,30 +205,23 @@ Signal_context_capability Signal_receiver::manage(Signal_context *context)
 	/* register context at process-wide registry */
 	signal_context_registry()->insert(&context->_registry_le);
 
-	bool try_again = true;
-	for (;;) {
-		try {
-
+	retry<Pd_session::Out_of_metadata>(
+		[&] () {
 			/* use signal context as imprint */
-			context->_cap = signal_connection()->alloc_context((long)context);
-			return context->_cap;
-
-		} catch (Signal_session::Out_of_metadata) {
-
-			/* give up if the error occurred a second time */
-			if (try_again) { try_again = false; }
-			else { break; }
-
+			context->_cap = env()->pd_session()->alloc_context(_cap, (long)context);
+		},
+		[&] () {
 			size_t const quota = 1024*sizeof(long);
 			char buf[64];
 			snprintf(buf, sizeof(buf), "ram_quota=%zu", quota);
 
-			PINF("upgrading quota donation for SIGNAL session (%zu bytes)", quota);
+			PINF("upgrading quota donation for PD session (%zu bytes)", quota);
 
-			env()->parent()->upgrade(signal_connection()->cap(), buf);
+			env()->parent()->upgrade(env()->pd_session_cap(), buf);
 		}
-	};
-	return Signal_context_capability();
+	);
+
+	return context->_cap;
 }
 
 
diff --git a/repos/base/src/core/include/assertion.h b/repos/base/src/core/include/assertion.h
new file mode 100644
index 0000000000..159a454a7c
--- /dev/null
+++ b/repos/base/src/core/include/assertion.h
@@ -0,0 +1,24 @@
+/*
+ * \brief  Assertion macros
+ * \author Norman Feske
+ * \date   2016-01-13
+ */
+
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef _CORE__INCLUDE__ASSERTION_H_
+#define _CORE__INCLUDE__ASSERTION_H_
+
+/* Genode includes */
+#include <base/printf.h>
+
+#define ASSERT_NEVER_CALLED \
+	PERR("Unexpected call of '%s' (%s:%u)", __FUNCTION__, __FILE__, __LINE__); \
+	for (;;); throw 0UL;
+
+#endif /* _CORE__INCLUDE__ASSERTION_H_ */
diff --git a/repos/base/src/core/include/core_env.h b/repos/base/src/core/include/core_env.h
index 02da1d5afd..0a3cd1ab36 100644
--- a/repos/base/src/core/include/core_env.h
+++ b/repos/base/src/core/include/core_env.h
@@ -22,12 +22,14 @@
 #include <base/env.h>
 #include <base/heap.h>
 #include <ram_session/client.h>
+#include <pd_session/client.h>
 #include <rm_session/capability.h>
 
 /* core includes */
 #include <platform.h>
 #include <core_parent.h>
 #include <core_rm_session.h>
+#include <core_pd_session.h>
 #include <cap_session_component.h>
 #include <ram_session_component.h>
 
@@ -113,30 +115,45 @@ namespace Genode {
 
 			typedef Synchronized_ram_session<Ram_session_component> Core_ram_session;
 
+			Core_parent           _core_parent;
+			Cap_session_component _cap_session;
+
 			enum { ENTRYPOINT_STACK_SIZE = 2048 * sizeof(Genode::addr_t) };
 
-			Core_parent                  _core_parent;
-			Cap_session_component        _cap_session;
 			Rpc_entrypoint               _entrypoint;
 			Core_rm_session              _rm_session;
 			Core_ram_session             _ram_session;
-			Heap                         _heap;
 			Ram_session_capability const _ram_session_cap;
 
+			/*
+			 * The core-local PD session is provided by a real RPC object
+			 * dispatched by the same entrypoint as the signal-source RPC
+			 * objects. This is needed to allow the 'Pd_session::submit'
+			 * method to issue out-of-order replies to
+			 * 'Signal_source::wait_for_signal' calls.
+			 */
+			Core_pd_session_component _pd_session_component;
+			Pd_session_client         _pd_session_client;
+
+			Heap _heap;
+
 		public:
 
 			/**
 			 * Constructor
 			 */
-			Core_env() :
+			Core_env()
+			:
 				_cap_session(platform()->core_mem_alloc(), "ram_quota=4K"),
 				_entrypoint(&_cap_session, ENTRYPOINT_STACK_SIZE, "entrypoint"),
 				_rm_session(&_entrypoint),
 				_ram_session(&_entrypoint, &_entrypoint,
 				             platform()->ram_alloc(), platform()->core_mem_alloc(),
 				             "ram_quota=4M", platform()->ram_alloc()->avail()),
-				_heap(&_ram_session, &_rm_session),
-				_ram_session_cap(_entrypoint.manage(&_ram_session))
+				_ram_session_cap(_entrypoint.manage(&_ram_session)),
+				_pd_session_component(_entrypoint /* XXX use a different entrypoint */),
+				_pd_session_client(_entrypoint.manage(&_pd_session_component)),
+				_heap(&_ram_session, &_rm_session)
 			{ }
 
 			/**
@@ -144,19 +161,20 @@ namespace Genode {
 			 */
 			~Core_env() { parent()->exit(0); }
 
-			Cap_session    *cap_session() { return &_cap_session; }
 			Rpc_entrypoint *entrypoint()  { return &_entrypoint; }
+			Cap_session    *cap_session() { return &_cap_session; }
 
 
 			/*******************
 			 ** Env interface **
 			 *******************/
 
-			Parent                 *parent()          { return &_core_parent; }
-			Ram_session            *ram_session()     { return &_ram_session; }
-			Ram_session_capability  ram_session_cap() { return  _ram_session_cap; }
-			Rm_session             *rm_session()      { return &_rm_session; }
-			Allocator              *heap()            { return &_heap; }
+			Parent                 *parent()          override { return &_core_parent; }
+			Ram_session            *ram_session()     override { return &_ram_session; }
+			Ram_session_capability  ram_session_cap() override { return  _ram_session_cap; }
+			Rm_session             *rm_session()      override { return &_rm_session; }
+			Pd_session             *pd_session()      override { return &_pd_session_client; }
+			Allocator              *heap()            override { return &_heap; }
 
 			Cpu_session *cpu_session()
 			{
@@ -169,10 +187,10 @@ namespace Genode {
 				return Cpu_session_capability();
 			}
 
-			Pd_session *pd_session()
+			Pd_session_capability pd_session_cap() override
 			{
 				PWRN("%s:%u not implemented", __FILE__, __LINE__);
-				return 0;
+				return Pd_session_capability();
 			}
 
 			void reinit(Capability<Parent>::Dst, long) { }
diff --git a/repos/base/src/core/include/core_pd_session.h b/repos/base/src/core/include/core_pd_session.h
new file mode 100644
index 0000000000..63b0a7befe
--- /dev/null
+++ b/repos/base/src/core/include/core_pd_session.h
@@ -0,0 +1,102 @@
+/*
+ * \brief  Core-specific pseudo PD session
+ * \author Norman Feske
+ * \date   2016-01-13
+ */
+
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef _CORE__INCLUDE__CORE_PD_SESSION_H_
+#define _CORE__INCLUDE__CORE_PD_SESSION_H_
+
+/* Genode includes */
+#include <base/rpc_server.h>
+#include <base/allocator.h>
+#include <pd_session/pd_session.h>
+
+/* core includes */
+#include <assertion.h>
+#include <signal_source_component.h>
+
+namespace Genode { class Core_pd_session_component; }
+
+
+class Genode::Core_pd_session_component : public Rpc_object<Pd_session>
+{
+	private:
+
+		Rpc_entrypoint &_signal_source_ep;
+
+	public:
+
+		/**
+		 * Constructor
+		 *
+		 * \param context_ep  entrypoint that serves the signal-source
+		 *                    components
+		 */
+		Core_pd_session_component(Rpc_entrypoint &signal_source_ep)
+		:
+			_signal_source_ep(signal_source_ep)
+		{ }
+
+		int bind_thread(Thread_capability thread) override
+		{
+			ASSERT_NEVER_CALLED;
+		}
+
+		int assign_parent(Capability<Parent> parent) override
+		{
+			ASSERT_NEVER_CALLED;
+		}
+
+		bool assign_pci(addr_t pci_config_memory_address, uint16_t) override
+		{
+			ASSERT_NEVER_CALLED;
+		}
+
+		Signal_source_capability alloc_signal_source() override
+		{
+			/*
+			 * Even though core does not receive any signals, this function is
+			 * called by the base-common initialization code on base-hw. We
+			 * can savely return an invalid capability as it is never used.
+			 */
+			return Signal_source_capability();
+		}
+
+		void free_signal_source(Signal_source_capability cap) override
+		{
+			ASSERT_NEVER_CALLED;
+		}
+
+		Capability<Signal_context>
+		alloc_context(Signal_source_capability source, unsigned long imprint) override
+		{
+			ASSERT_NEVER_CALLED;
+		}
+
+		void free_context(Capability<Signal_context> cap) override
+		{
+			ASSERT_NEVER_CALLED;
+		}
+
+		void submit(Capability<Signal_context> cap, unsigned cnt = 1) override
+		{
+			_signal_source_ep.apply(cap, [&] (Signal_context_component *context) {
+				if (!context) {
+					PDBG("invalid signal-context capability");
+					return;
+				}
+
+				context->source()->submit(context, cnt);
+			});
+		}
+};
+
+#endif /* _CORE__INCLUDE__CORE_PD_SESSION_H_ */
diff --git a/repos/base/src/core/include/pd_root.h b/repos/base/src/core/include/pd_root.h
index a4bc2809e3..6c0d9c572e 100644
--- a/repos/base/src/core/include/pd_root.h
+++ b/repos/base/src/core/include/pd_root.h
@@ -25,19 +25,21 @@ namespace Genode {
 }
 
 
-class Genode::Pd_root
-: public Genode::Root_component<Genode::Pd_session_component>
+class Genode::Pd_root : public Genode::Root_component<Genode::Pd_session_component>
 {
 	private:
 
-		Rpc_entrypoint *_thread_ep;
-		Allocator      *_md_alloc;
+		Rpc_entrypoint &_thread_ep;
+		Allocator      &_md_alloc;
 
 	protected:
 
 		Pd_session_component *_create_session(const char *args)
 		{
+			/* XXX use separate entrypoint for PD sessions */
 			return new (md_alloc()) Pd_session_component(_thread_ep,
+			                                             _thread_ep,
+			                                             _thread_ep,
 			                                             _md_alloc, args);
 		}
 
@@ -61,7 +63,7 @@ class Genode::Pd_root
 		        Rpc_entrypoint *thread_ep,
 		        Allocator      *md_alloc)
 		: Root_component<Pd_session_component>(session_ep, md_alloc),
-		  _thread_ep(thread_ep), _md_alloc(md_alloc) { }
+		  _thread_ep(*thread_ep), _md_alloc(*md_alloc) { }
 };
 
 #endif /* _CORE__INCLUDE__PD_ROOT_H_ */
diff --git a/repos/base/src/core/include/pd_session_component.h b/repos/base/src/core/include/pd_session_component.h
index 824701d4f5..f0b41ed32c 100644
--- a/repos/base/src/core/include/pd_session_component.h
+++ b/repos/base/src/core/include/pd_session_component.h
@@ -2,11 +2,12 @@
  * \brief  Core-specific instance of the PD session interface
  * \author Christian Helmuth
  * \author Stefan Kalkowski
+ * \author Norman Feske
  * \date   2006-07-17
  */
 
 /*
- * Copyright (C) 2006-2013 Genode Labs GmbH
+ * Copyright (C) 2006-2016 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.
@@ -23,6 +24,7 @@
 
 /* core includes */
 #include <platform_pd.h>
+#include <signal_broker.h>
 
 namespace Genode { class Pd_session_component; }
 
@@ -48,35 +50,86 @@ class Genode::Pd_session_component : public Rpc_object<Pd_session>
 
 		Allocator_guard    _md_alloc;   /* guarded meta-data allocator */
 		Platform_pd        _pd;
-		Parent_capability  _parent;
-		Rpc_entrypoint    *_thread_ep;
+		Capability<Parent> _parent;
+		Rpc_entrypoint    &_thread_ep;
+
+		Signal_broker _signal_broker;
 
 		size_t _ram_quota(char const * args) {
 			return Arg_string::find_arg(args, "ram_quota").long_value(0); }
 
 	public:
 
-		Pd_session_component(Rpc_entrypoint * thread_ep,
-		                     Allocator      * md_alloc,
-		                     char const     * args)
-		: _label(args),
-		  _md_alloc(md_alloc, _ram_quota(args)),
-		  _pd(&_md_alloc, _label.string),
-		  _thread_ep(thread_ep) { }
+		/**
+		 * Constructor
+		 *
+		 * \param receiver_ep  entrypoint holding signal-receiver component
+		 *                     objects
+		 * \param context_ep   global pool of all signal contexts
+		 * \param md_alloc     backing-store allocator for
+		 *                     signal-context component objects
+		 *
+		 * To maintain proper synchronization, 'receiver_ep' must be
+		 * the same entrypoint as used for the signal-session component.
+		 * The 'signal_context_ep' is only used for associative array
+		 * to map signal-context capabilities to 'Signal_context_component'
+		 * objects and as capability allocator for such objects.
+		 */
+
+		Pd_session_component(Rpc_entrypoint &thread_ep,
+		                     Rpc_entrypoint &receiver_ep,
+		                     Rpc_entrypoint &context_ep,
+		                     Allocator      &md_alloc,
+		                     char const     *args)
+		:
+			_label(args),
+			_md_alloc(&md_alloc, _ram_quota(args)),
+			_pd(&_md_alloc, _label.string),
+			_thread_ep(thread_ep),
+			_signal_broker(_md_alloc, receiver_ep, context_ep)
+		{ }
 
 		/**
 		 * Register quota donation at allocator guard
 		 */
-		void upgrade_ram_quota(size_t ram_quota) {
-			_md_alloc.upgrade(ram_quota); }
+		void upgrade_ram_quota(size_t ram_quota);
 
 
-		/**************************/
-		/** PD session interface **/
-		/**************************/
+		/**************************
+		 ** PD session interface **
+		 **************************/
 
-		int bind_thread(Thread_capability);
-		int assign_parent(Parent_capability);
+		int bind_thread(Thread_capability) override;
+		int assign_parent(Capability<Parent>) override;
+		bool assign_pci(addr_t, uint16_t) override;
+
+		Signal_source_capability alloc_signal_source() override
+		{
+			try {
+				return _signal_broker.alloc_signal_source(); }
+			catch (Genode::Allocator::Out_of_memory) {
+				throw Pd_session::Out_of_metadata(); }
+		}
+
+		void free_signal_source(Signal_source_capability sig_rec_cap) override {
+			_signal_broker.free_signal_source(sig_rec_cap); }
+
+		Signal_context_capability
+		alloc_context(Signal_source_capability sig_rec_cap, unsigned long imprint) override
+		{
+			try {
+				return _signal_broker.alloc_context(sig_rec_cap, imprint); }
+			catch (Genode::Allocator::Out_of_memory) {
+				throw Pd_session::Out_of_metadata(); }
+			catch (Signal_broker::Invalid_signal_source) {
+				throw Pd_session::Invalid_signal_source(); }
+		}
+
+		void free_context(Signal_context_capability cap) override {
+			_signal_broker.free_context(cap); }
+
+		void submit(Signal_context_capability cap, unsigned n) override {
+			_signal_broker.submit(cap, n); }
 };
 
 #endif /* _CORE__INCLUDE__PD_SESSION_COMPONENT_H_ */
diff --git a/repos/base/src/core/include/signal_broker.h b/repos/base/src/core/include/signal_broker.h
new file mode 100644
index 0000000000..d401bd8307
--- /dev/null
+++ b/repos/base/src/core/include/signal_broker.h
@@ -0,0 +1,110 @@
+/*
+ * \brief  Mechanism to deliver signals via core
+ * \author Norman Feske
+ * \date   2016-01-04
+ */
+
+/*
+ * Copyright (C) 2016 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__SIGNAL_BROKER_H_
+#define _CORE__INCLUDE__SIGNAL_BROKER_H_
+
+#include <signal_source_component.h>
+#include <signal_source/capability.h>
+
+namespace Genode { class Signal_broker; }
+
+class Genode::Signal_broker
+{
+	private:
+
+		Allocator                        &_md_alloc;
+		Rpc_entrypoint                   &_source_ep;
+		Rpc_entrypoint                   &_context_ep;
+		Signal_source_component           _source;
+		Signal_source_capability          _source_cap;
+		Tslab<Signal_context_component,
+		      960*sizeof(long)>           _contexts_slab { &_md_alloc };
+
+	public:
+
+		class Invalid_signal_source : public Exception { };
+
+		Signal_broker(Allocator      &md_alloc,
+		              Rpc_entrypoint &source_ep,
+		              Rpc_entrypoint &context_ep)
+		:
+			_md_alloc(md_alloc),
+			_source_ep(source_ep),
+			_context_ep(context_ep),
+			_source(&_context_ep),
+			_source_cap(_source_ep.manage(&_source))
+		{ }
+
+		~Signal_broker()
+		{
+			/* remove source from entrypoint */
+			_source_ep.dissolve(&_source);
+
+			/* free all signal contexts */
+			while (Signal_context_component *r = _contexts_slab.first_object())
+				free_context(r->cap());
+		}
+
+		Signal_source_capability alloc_signal_source() { return _source_cap; }
+
+		void free_signal_source(Signal_source_capability) { }
+
+		Signal_context_capability
+		alloc_context(Signal_source_capability, unsigned long imprint)
+		{
+			/*
+			 * XXX  For now, we ignore the signal-source argument as we
+			 *      create only a single receiver for each PD.
+			 */
+			Signal_context_component *context = new (&_contexts_slab)
+				Signal_context_component(imprint, &_source);
+
+			return _context_ep.manage(context);
+		}
+
+		void free_context(Signal_context_capability context_cap)
+		{
+			Signal_context_component *context;
+
+			_context_ep.apply(context_cap, [&] (Signal_context_component *c) {
+				context = c;
+				if (!context) {
+					PWRN("specified signal-context capability has wrong type");
+					return;
+				}
+
+				_context_ep.dissolve(context);
+			});
+			destroy(&_contexts_slab, context);
+		}
+
+		void submit(Signal_context_capability cap, unsigned cnt)
+		{
+			_source_ep.apply(cap, [&] (Signal_context_component *context) {
+				if (!context) {
+					/*
+					 * We do not use PWRN() to enable the build system to
+					 * suppress this warning in release mode (SPECS +=
+					 * release).
+					 */
+					PDBG("invalid signal-context capability");
+					return;
+				}
+
+				context->source()->submit(context, cnt);
+			});
+		}
+};
+
+#endif /* _CORE__INCLUDE__SIGNAL_BROKER_H_ */
diff --git a/repos/base/src/core/include/signal_root.h b/repos/base/src/core/include/signal_root.h
deleted file mode 100644
index 3ee58ca47f..0000000000
--- a/repos/base/src/core/include/signal_root.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * \brief  Signal root interface
- * \author Norman Feske
- * \date   2009-08-05
- */
-
-/*
- * 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.
- */
-
-#ifndef _CORE__INCLUDE__SIGNAL_ROOT_H_
-#define _CORE__INCLUDE__SIGNAL_ROOT_H_
-
-/* Genode includes */
-#include <root/component.h>
-
-/* core includes */
-#include <signal_session_component.h>
-
-namespace Genode {
-
-	class Signal_handler
-	{
-		private:
-
-			enum { STACK_SIZE = sizeof(addr_t)*1024 };
-			Rpc_entrypoint _ep;
-
-		public:
-
-			Signal_handler(Cap_session *cap_session) :
-				_ep(cap_session, STACK_SIZE, "signal")
-			{ }
-
-			Rpc_entrypoint *entrypoint() { return &_ep; }
-	};
-
-
-	class Signal_root : private Signal_handler,
-	                    public Root_component<Signal_session_component>
-	{
-		protected:
-
-			Signal_session_component *_create_session(const char *args)
-			{
-				size_t ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0);
-				return new (md_alloc())
-					Signal_session_component(entrypoint(), entrypoint(),
-					                         md_alloc(), ram_quota);
-			}
-
-			void _upgrade_session(Signal_session_component *s, const char *args)
-			{
-				size_t ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0);
-				s->upgrade_ram_quota(ram_quota);
-			}
-
-		public:
-
-			/**
-			 * Constructor
-			 *
-			 * \param md_alloc    meta-data allocator to be used by root component
-			 */
-			Signal_root(Allocator *md_alloc, Cap_session *cap_session)
-			:
-				Signal_handler(cap_session),
-				Root_component<Signal_session_component>(entrypoint(), md_alloc)
-			{ }
-	};
-}
-
-#endif /* _CORE__INCLUDE__SIGNAL_ROOT_H_ */
diff --git a/repos/base/src/core/include/signal_session_component.h b/repos/base/src/core/include/signal_session_component.h
deleted file mode 100644
index 8a148a8440..0000000000
--- a/repos/base/src/core/include/signal_session_component.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * \brief  Signal service
- * \author Norman Feske
- * \date   2009-08-05
- */
-
-/*
- * 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.
- */
-
-#ifndef _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_
-#define _CORE__INCLUDE__SIGNAL_SESSION_COMPONENT_H_
-
-#include <signal_session/signal_session.h>
-#include <signal_session/source_rpc_object.h>
-#include <base/allocator_guard.h>
-#include <base/tslab.h>
-#include <base/lock.h>
-#include <base/rpc_client.h>
-#include <base/rpc_server.h>
-#include <util/fifo.h>
-#include <base/signal.h>
-
-namespace Genode {
-
-	class Signal_source_component;
-	class Signal_context_component;
-
-	typedef Fifo<Signal_context_component> Signal_queue;
-
-	class Signal_context_component : public Rpc_object<Signal_context>,
-	                                 public Signal_queue::Element
-	{
-		private:
-
-			long                     _imprint;
-			int                      _cnt;
-			Signal_source_component *_source;
-
-		public:
-
-			/**
-			 * Constructor
-			 */
-			Signal_context_component(long imprint, Signal_source_component *source)
-			: _imprint(imprint), _cnt(0), _source(source) { }
-
-			/**
-			 * De-constructor
-			 */
-			~Signal_context_component(); 
-
-			/**
-			 * Increment number of signals to be delivered at once
-			 */
-			void increment_signal_cnt(int increment) { _cnt += increment; }
-
-			/**
-			 * Reset number of pending signals
-			 */
-			void reset_signal_cnt() { _cnt = 0; }
-
-			long                     imprint() { return _imprint; }
-			int                      cnt()     { return _cnt; }
-			Signal_source_component *source()  { return _source; }
-	};
-
-
-	class Signal_source_component : public Signal_source_rpc_object
-	{
-		/**
-		 * Helper for clean destruction of signal-source component
-		 *
-		 * Normally, reply capabilities are implicitly destroyed when answering
-		 * an RPC call. But when destructing a signal session while a signal-
-		 * source client is blocking on a 'wait_for_signal' call, this
-		 * blocking call will never return via the normal control flow
-		 * (signal submission). In this case, the reply capability would
-		 * outlive the signal session. To avoid the leakage of such reply
-		 * capabilities, we let the signal-session destructor perform a
-		 * core-local RPC call to the so-called 'Finalizer' object, which has
-		 * the sole purpose of replying to the last outstanding
-		 * 'wait_for_signal' call and thereby releasing the corresponding
-		 * reply capability.
-		 */
-		struct Finalizer
-		{
-			GENODE_RPC(Rpc_exit, void, exit);
-			GENODE_RPC_INTERFACE(Rpc_exit);
-		};
-
-		struct Finalizer_component : Rpc_object<Finalizer, Finalizer_component>
-		{
-			Signal_source_component &source;
-
-			Finalizer_component(Signal_source_component &source)
-			: source(source) { }
-
-			void exit();
-		};
-
-		private:
-
-			Signal_queue        _signal_queue;
-			Rpc_entrypoint     *_entrypoint;
-			Native_capability   _reply_cap;
-			Finalizer_component _finalizer;
-			Capability<Finalizer> _finalizer_cap;
-
-		public:
-
-			/**
-			 * Constructor
-			 */
-			Signal_source_component(Rpc_entrypoint *rpc_entrypoint);
-
-			~Signal_source_component();
-
-			void release(Signal_context_component *context);
-
-			void submit(Signal_context_component *context,
-			            Ipc_ostream              *ostream,
-			            int                       cnt);
-
-
-			/*****************************
-			 ** Signal-source interface **
-			 *****************************/
-
-			Signal wait_for_signal();
-	};
-
-
-	class Signal_session_component : public Rpc_object<Signal_session>
-	{
-		private:
-
-			Rpc_entrypoint                       *_source_ep;
-			Rpc_entrypoint                       *_context_ep;
-			Signal_source_component               _source;
-			Signal_source_capability              _source_cap;
-			Allocator_guard                       _md_alloc;
-			Tslab<Signal_context_component,
-			      960*sizeof(long)>               _contexts_slab;
-			Ipc_ostream                          *_ipc_ostream;
-
-		public:
-
-			/**
-			 * Constructor
-			 *
-			 * \param source_ep    entrypoint holding signal-source component
-			 *                     objects
-			 * \param context_ep   global pool of all signal contexts
-			 * \param md_alloc     backing-store allocator for
-			 *                     signal-context component objects
-			 *
-			 * To maintain proper synchronization, 'signal_source_ep' must be
-			 * the same entrypoint as used for the signal-session component.
-			 * The 'signal_context_ep' is only used for associative array
-			 * to map signal-context capabilities to 'Signal_context_component'
-			 * objects and as capability allocator for such objects.
-			 */
-			Signal_session_component(Rpc_entrypoint *source_ep,
-			                         Rpc_entrypoint *context_ep,
-			                         Allocator      *context_md_alloc,
-			                         size_t          ram_quota);
-
-			~Signal_session_component();
-
-			/**
-			 * Register quota donation at allocator guard
-			 */
-			void upgrade_ram_quota(size_t ram_quota) { _md_alloc.upgrade(ram_quota); }
-
-
-			/******************************
-			 ** Signal-session interface **
-			 ******************************/
-
-			Signal_source_capability signal_source();
-			Signal_context_capability alloc_context(long imprint);
-			void free_context(Signal_context_capability context_cap);
-			void submit(Signal_context_capability context_cap, unsigned cnt);
-
-
-			/**************************
-			 ** Rpc_object interface **
-			 **************************/
-
-			Rpc_exception_code dispatch(int opcode, Ipc_istream &is, Ipc_ostream &os)
-			{
-				/*
-				 * Make IPC output stream available to the submit function. The
-				 * stream is used to carry signal payload for the out-of-order
-				 * handling of 'wait_for_signal' replies.
-				 */
-				_ipc_ostream = &os;
-
-				/* dispatch RPC */
-				return Rpc_object<Signal_session>::dispatch(opcode, is, os);
-			}
-	};
-}
-
-#endif /* _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_ */
diff --git a/repos/base/src/core/include/signal_source_component.h b/repos/base/src/core/include/signal_source_component.h
new file mode 100644
index 0000000000..7589577646
--- /dev/null
+++ b/repos/base/src/core/include/signal_source_component.h
@@ -0,0 +1,143 @@
+/*
+ * \brief  Signal-delivery mechanism
+ * \author Norman Feske
+ * \date   2009-08-05
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_
+#define _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_
+
+#include <signal_source/rpc_object.h>
+#include <base/allocator_guard.h>
+#include <base/tslab.h>
+#include <base/lock.h>
+#include <base/rpc_client.h>
+#include <base/rpc_server.h>
+#include <util/fifo.h>
+#include <base/signal.h>
+
+namespace Genode {
+
+	class Signal_context_component;
+	class Signal_source_component;
+
+	typedef Fifo<Signal_context_component> Signal_queue;
+}
+
+
+class Genode::Signal_context_component : public Rpc_object<Signal_context>,
+                                         public Signal_queue::Element
+{
+	private:
+
+		long                     _imprint;
+		int                      _cnt;
+		Signal_source_component *_source;
+
+	public:
+
+		/**
+		 * Constructor
+		 */
+		Signal_context_component(long imprint,
+		                         Signal_source_component *source)
+		: _imprint(imprint), _cnt(0), _source(source) { }
+
+		/**
+		 * Destructor
+		 */
+		inline ~Signal_context_component();
+
+		/**
+		 * Increment number of signals to be delivered at once
+		 */
+		void increment_signal_cnt(int increment) { _cnt += increment; }
+
+		/**
+		 * Reset number of pending signals
+		 */
+		void reset_signal_cnt() { _cnt = 0; }
+
+		long                          imprint()  { return _imprint; }
+		int                           cnt()      { return _cnt; }
+		Signal_source_component      *source()   { return _source; }
+};
+
+
+class Genode::Signal_source_component : public Signal_source_rpc_object
+{
+	/**
+	 * Helper for clean destruction of signal-receiver component
+	 *
+	 * Normally, reply capabilities are implicitly destroyed when answering
+	 * an RPC call. But when destructing a signal session while a signal-
+	 * receiver client is blocking on a 'wait_for_signal' call, this
+	 * blocking call will never return via the normal control flow
+	 * (signal submission). In this case, the reply capability would
+	 * outlive the signal session. To avoid the leakage of such reply
+	 * capabilities, we let the signal-session destructor perform a
+	 * core-local RPC call to the so-called 'Finalizer' object, which has
+	 * the sole purpose of replying to the last outstanding
+	 * 'wait_for_signal' call and thereby releasing the corresponding
+	 * reply capability.
+	 */
+	struct Finalizer
+	{
+		GENODE_RPC(Rpc_exit, void, exit);
+		GENODE_RPC_INTERFACE(Rpc_exit);
+	};
+
+	struct Finalizer_component : Rpc_object<Finalizer, Finalizer_component>
+	{
+		Signal_source_component &source;
+
+		Finalizer_component(Signal_source_component &source)
+		: source(source) { }
+
+		void exit();
+	};
+
+	private:
+
+		Signal_queue          _signal_queue;
+		Rpc_entrypoint       *_entrypoint;
+		Native_capability     _reply_cap;
+		Finalizer_component   _finalizer;
+		Capability<Finalizer> _finalizer_cap;
+
+	public:
+
+		/**
+		 * Constructor
+		 */
+		Signal_source_component(Rpc_entrypoint *rpc_entrypoint);
+
+		~Signal_source_component();
+
+		void release(Signal_context_component *context);
+
+		void submit(Signal_context_component *context,
+		            unsigned long             cnt);
+
+		/*****************************
+		 ** Signal-receiver interface **
+		 *****************************/
+
+		Signal wait_for_signal() override;
+};
+
+
+Genode::Signal_context_component::~Signal_context_component()
+{
+	if (is_enqueued() && _source)
+		_source->release(this);
+}
+
+#endif /* _CORE__INCLUDE__SIGNAL_SOURCE_COMPONENT_H_ */
diff --git a/repos/base/src/core/main.cc b/repos/base/src/core/main.cc
index 59c7c093e1..ae20608663 100644
--- a/repos/base/src/core/main.cc
+++ b/repos/base/src/core/main.cc
@@ -33,7 +33,6 @@
 #include <log_root.h>
 #include <io_mem_root.h>
 #include <irq_root.h>
-#include <signal_root.h>
 #include <trace/root.h>
 #include <platform_services.h>
 
@@ -213,16 +212,6 @@ int main()
 	 */
 	static Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
 
-	/**
-	 * Provide signal service before other services to enable the use of signal
-	 * connection during service initialization. This has been introduced due
-	 * to the use of the signal framework for paging (RM service) in base-hw.
-	 */
-	static Signal_root signal_root(&sliced_heap, core_env()->cap_session());
-	char const * const signal_name = Signal_session::service_name();
-	static Local_service signal_service(signal_name, &signal_root);
-	local_services.insert(&signal_service);
-
 	static Cap_root     cap_root     (e, &sliced_heap);
 	static Ram_root     ram_root     (e, e, platform()->ram_alloc(), &sliced_heap);
 	static Rom_root     rom_root     (e, e, platform()->rom_fs(), &sliced_heap);
diff --git a/repos/base/src/core/pd_assign_pci.cc b/repos/base/src/core/pd_assign_pci.cc
new file mode 100644
index 0000000000..653fa816f2
--- /dev/null
+++ b/repos/base/src/core/pd_assign_pci.cc
@@ -0,0 +1,22 @@
+/*
+ * \brief  Core implementation of the PD session interface
+ * \author Norman Feske
+ * \date   2016-01-13
+ *
+ * This dummy is used on all kernels with no IOMMU support.
+ */
+
+/*
+ * Copyright (C) 2016 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-local includes */
+#include <pd_session_component.h>
+
+using namespace Genode;
+
+bool Pd_session_component::assign_pci(addr_t, uint16_t) { return false; }
+
diff --git a/repos/base/src/core/pd_session_component.cc b/repos/base/src/core/pd_session_component.cc
index e78a51b309..71d1a7c214 100644
--- a/repos/base/src/core/pd_session_component.cc
+++ b/repos/base/src/core/pd_session_component.cc
@@ -26,7 +26,7 @@ using namespace Genode;
 
 int Pd_session_component::bind_thread(Thread_capability thread)
 {
-	return _thread_ep->apply(thread, [&] (Cpu_thread_component *cpu_thread) {
+	return _thread_ep.apply(thread, [&] (Cpu_thread_component *cpu_thread) {
 		if (!cpu_thread) return -1;
 
 		if (cpu_thread->bound()) {
diff --git a/repos/base/src/core/pd_upgrade_ram_quota.cc b/repos/base/src/core/pd_upgrade_ram_quota.cc
new file mode 100644
index 0000000000..2422105f46
--- /dev/null
+++ b/repos/base/src/core/pd_upgrade_ram_quota.cc
@@ -0,0 +1,24 @@
+/*
+ * \brief  Core implementation of the PD session interface
+ * \author Norman Feske
+ * \date   2016-01-13
+ */
+
+/*
+ * Copyright (C) 2016 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-local includes */
+#include <pd_session_component.h>
+
+using namespace Genode;
+
+
+void Pd_session_component::upgrade_ram_quota(size_t ram_quota)
+{
+	_md_alloc.upgrade(ram_quota);
+}
+
diff --git a/repos/base/src/core/signal_session_component.cc b/repos/base/src/core/signal_session_component.cc
deleted file mode 100644
index 645c971a91..0000000000
--- a/repos/base/src/core/signal_session_component.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * \brief  Implementation of the SIGNAL interface
- * \author Norman Feske
- * \date   2009-08-11
- */
-
-/*
- * 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 <base/printf.h>
-
-/* core includes */
-#include <signal_session_component.h>
-
-using namespace Genode;
-
-
-/******************************
- ** Signal-session component **
- ******************************/
-
-Signal_session_component::Signal_session_component(Rpc_entrypoint *source_ep,
-                                                   Rpc_entrypoint *context_ep,
-                                                   Allocator      *context_md_alloc,
-                                                   size_t          ram_quota)
-:
-	_source_ep(source_ep),
-	_context_ep(context_ep),
-	_source(source_ep),
-	_source_cap(_source_ep->manage(&_source)),
-	_md_alloc(context_md_alloc, ram_quota),
-	_contexts_slab(&_md_alloc)
-{ }
-
-
-Signal_session_component::~Signal_session_component()
-{
-	/* remove _signal_source from entrypoint */
-	_source_ep->dissolve(&_source);
-
-	/* free all signal contexts */
-	while (Signal_context_component *r = _contexts_slab.first_object())
-		free_context(r->cap());
-}
-
-
-Signal_source_capability Signal_session_component::signal_source()
-{
-	return _source_cap;
-}
-
-
-Signal_context_capability Signal_session_component::alloc_context(long imprint)
-{
-	Signal_context_component *context;
-
-	try { context = new (&_contexts_slab)
-	                Signal_context_component(imprint, &_source); }
-
-	catch (Allocator::Out_of_memory) { throw Out_of_metadata(); }
-
-	/* return unique capability for the signal context */
-	return _context_ep->manage(context);
-}
-
-
-void Signal_session_component::free_context(Signal_context_capability context_cap)
-{
-	Signal_context_component *context;
-	_context_ep->apply(context_cap, [&] (Signal_context_component *c) {
-		context = c;
-		if (!context) {
-			PWRN("specified signal-context capability has wrong type");
-			return;
-		}
-
-		_context_ep->dissolve(context);
-	});
-	destroy(&_contexts_slab, context);
-}
-
-
-void Signal_session_component::submit(Signal_context_capability context_cap,
-                                      unsigned                  cnt)
-{
-	_context_ep->apply(context_cap, [&] (Signal_context_component *context) {
-		if (!context) {
-			/*
-			 * We do not use PWRN() to enable the build system to suppress this
-			 * warning in release mode (SPECS += release).
-			 */
-			PDBG("invalid signal-context capability");
-			return;
-		}
-
-		context->source()->submit(context, _ipc_ostream, cnt);
-	});
-}
-
-
-Signal_context_component::~Signal_context_component()
-{
-	if (is_enqueued() && _source)
-		_source->release(this);
-}
diff --git a/repos/base/src/core/signal_source_component.cc b/repos/base/src/core/signal_source_component.cc
index 110ad5ce5e..2c0d4d9fee 100644
--- a/repos/base/src/core/signal_source_component.cc
+++ b/repos/base/src/core/signal_source_component.cc
@@ -16,7 +16,7 @@
 #include <base/printf.h>
 
 /* core includes */
-#include <signal_session_component.h>
+#include <signal_source_component.h>
 
 using namespace Genode;
 
@@ -33,8 +33,7 @@ void Signal_source_component::release(Signal_context_component *context)
 
 
 void Signal_source_component::submit(Signal_context_component *context,
-                                     Ipc_ostream              *ostream,
-                                     int                       cnt)
+                                     unsigned long             cnt)
 {
 	/*
 	 * If the client does not block in 'wait_for_signal', the
@@ -49,8 +48,7 @@ void Signal_source_component::submit(Signal_context_component *context,
 	 */
 	if (_reply_cap.valid()) {
 
-		*ostream << Signal(context->imprint(), context->cnt());
-		_entrypoint->explicit_reply(_reply_cap, 0);
+		_entrypoint->reply_signal_info(_reply_cap, context->imprint(), context->cnt());
 
 		/*
 		 * We unblocked the client and, therefore, can invalidate
@@ -108,6 +106,6 @@ void Signal_source_component::Finalizer_component::exit()
 	if (!source._reply_cap.valid())
 		return;
 
-	source._entrypoint->explicit_reply(source._reply_cap, 0);
+	source._entrypoint->reply_signal_info(source._reply_cap, 0, 0);
 	source._reply_cap = Untyped_capability();
 }