diff --git a/base/run/mp_server.run b/base/run/mp_server.run
new file mode 100644
index 0000000000..6d4816bae2
--- /dev/null
+++ b/base/run/mp_server.run
@@ -0,0 +1,78 @@
+#
+# \brief Test to start and call RPC entrypoint on all available CPUs
+# \author Norman Feske
+# \author Alexander Boettcher
+#
+
+if {![have_spec nova] && ![have_spec foc]} {
+ puts "Platform is unsupported."
+ exit 0
+}
+
+build "core init test/mp_server"
+
+create_boot_directory
+
+install_config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+build_boot_image "core init test-server-mp"
+
+if {[is_qemu_available]} {
+ set want_cpus 2
+ append qemu_args " -nographic -m 64 -smp $want_cpus,cores=$want_cpus "
+}
+
+# run the test
+run_genode_until {\[init -\> test-server-mp\] done.*\n} 20
+
+set cpus [regexp -inline {Detected [0-9]+ CPU[ s].*\n} $output]
+set cpus [regexp -inline {[0-9]+} $cpus]
+
+if {[is_qemu_available]} {
+ if {$want_cpus != $cpus} {
+ puts "CPU count is not as expected: $want_cpus != $cpus"
+ exit 1;
+ }
+}
+
+# pay only attention to the output of init and its children
+grep_output {^\[init }
+
+unify_output {transfer cap [a-f0-9]+} "transfer cap UNIFIED"
+unify_output {yes - idx [a-f0-9]+} "yes - idx UNIFIED"
+unify_output {\- received cap [a-f0-9]+} "- received cap UNIFIED"
+
+compare_output_to {
+ [init -> test-server-mp] --- test-mp_server started ---
+ [init -> test-server-mp] Detected 2 CPUs.
+ [init -> test-server-mp] call server on CPU 0
+ [init -> test-server-mp] function test_untyped: got value 0
+ [init -> test-server-mp] call server on CPU 1
+ [init -> test-server-mp] function test_untyped: got value 1
+ [init -> test-server-mp] call server on CPU 0 - transfer cap UNIFIED
+ [init -> test-server-mp] function test_cap: capability is valid ? yes - idx UNIFIED
+ [init -> test-server-mp] call server on CPU 1 - transfer cap UNIFIED
+ [init -> test-server-mp] function test_cap: capability is valid ? yes - idx UNIFIED
+ [init -> test-server-mp] call server on CPU 0 - transfer cap UNIFIED
+ [init -> test-server-mp] function test_cap_reply: capability is valid ? yes - idx UNIFIED
+ [init -> test-server-mp] got from server on CPU 0 - received cap UNIFIED
+ [init -> test-server-mp] call server on CPU 1 - transfer cap UNIFIED
+ [init -> test-server-mp] function test_cap_reply: capability is valid ? yes - idx UNIFIED
+ [init -> test-server-mp] got from server on CPU 1 - received cap UNIFIED
+ [init -> test-server-mp] done
+}
diff --git a/base/src/test/mp_server/main.cc b/base/src/test/mp_server/main.cc
new file mode 100644
index 0000000000..2fbfa8a95d
--- /dev/null
+++ b/base/src/test/mp_server/main.cc
@@ -0,0 +1,138 @@
+/*
+ * \brief Multiprocessor test for a server having multiple Rpc_entrypoints on
+ * different CPUs
+ * \author Alexander Boettcher
+ * \date 2013-07-19
+ */
+
+/*
+ * Copyright (C) 2013 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU General Public License version 2.
+ */
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+namespace Test {
+
+ /**
+ * Test session interface definition
+ */
+ struct Session : Genode::Session
+ {
+ static const char *service_name() { return "MP_RPC_TEST"; }
+
+ GENODE_RPC(Rpc_test_untyped, void, test_untyped, unsigned);
+ GENODE_RPC(Rpc_test_cap, void, test_cap, Genode::Native_capability);
+ GENODE_RPC(Rpc_test_cap_reply, Genode::Native_capability,
+ test_cap_reply, Genode::Native_capability);
+ GENODE_RPC_INTERFACE(Rpc_test_untyped, Rpc_test_cap, Rpc_test_cap_reply);
+ };
+
+ struct Client : Genode::Rpc_client
+ {
+ Client(Capability cap) : Rpc_client(cap) { }
+
+ void test_untyped(unsigned value) { call(value); }
+ void test_cap(Genode::Native_capability cap) { call(cap); }
+ Genode::Native_capability test_cap_reply(Genode::Native_capability cap) {
+ return call(cap); }
+ };
+
+ struct Component : Genode::Rpc_object
+ {
+ /* Test to just sent plain words (untyped items) */
+ void test_untyped(unsigned);
+ /* Test to transfer a object capability during send */
+ void test_cap(Genode::Native_capability);
+ /* Test to transfer a object capability during send+reply */
+ Genode::Native_capability test_cap_reply(Genode::Native_capability);
+ };
+
+ typedef Genode::Capability Capability;
+
+ /**
+ * Session implementation
+ */
+ void Component::test_untyped(unsigned value) {
+ Genode::printf("function %s: got value %u\n", __FUNCTION__, value);
+ }
+
+ void Component::test_cap(Genode::Native_capability cap) {
+ Genode::printf("function %s: capability is valid ? %s - idx %lx\n",
+ __FUNCTION__, cap.valid() ? "yes" : "no",
+ cap.local_name());
+ }
+
+ Genode::Native_capability Component::test_cap_reply(Genode::Native_capability cap) {
+ Genode::printf("function %s: capability is valid ? %s - idx %lx\n",
+ __FUNCTION__, cap.valid() ? "yes" : "no",
+ cap.local_name());
+ return cap;
+ }
+}
+
+/**
+ * Set up a server running on every CPU one Rpc_entrypoint
+ */
+int main(int argc, char **argv)
+{
+ using namespace Genode;
+
+ printf("--- test-mp_server started ---\n");
+
+ unsigned cpus = env()->cpu_session()->num_cpus();
+ printf("Detected %u CPU%c.\n", cpus, cpus > 1 ? 's' : ' ');
+
+ enum { STACK_SIZE = 4096 };
+
+ static Cap_connection cap;
+ Rpc_entrypoint ** eps = new (env()->heap()) Rpc_entrypoint*[cpus];
+ for (unsigned i = 0; i < cpus; i++)
+ eps[i] = new (env()->heap()) Rpc_entrypoint(&cap, STACK_SIZE, "rpc en",
+ true, i);
+
+ /* XXX using the same object and putting it to different queues fails XXX */
+ Test::Component * components = new (env()->heap()) Test::Component[cpus];
+
+ Test::Capability * caps = new (env()->heap()) Test::Capability[cpus];
+ for (unsigned i = 0; i < cpus; i++)
+ caps[i] = eps[i]->manage(&components[i]);
+
+ Test::Client ** clients = new (env()->heap()) Test::Client*[cpus];
+ for (unsigned i = 0; i < cpus; i++)
+ clients[i] = new (env()->heap()) Test::Client(caps[i]);
+
+ /* Test: Invoke RPC entrypoint on different CPUs */
+ for (unsigned i = 0; i < cpus; i++) {
+ printf("call server on CPU %u\n", i);
+ clients[i]->test_untyped(i);
+ }
+
+ /* Test: Transfer a capability to RPC Entrypoints on different CPUs */
+ for (unsigned i = 0; i < cpus; i++) {
+ Native_capability cap = caps[0];
+ printf("call server on CPU %u - transfer cap %lx\n", i, cap.local_name());
+ clients[i]->test_cap(cap);
+ }
+
+ /* Test: Transfer a capability to RPC Entrypoints and back */
+ for (unsigned i = 0; i < cpus; i++) {
+ Native_capability cap = caps[0];
+ printf("call server on CPU %u - transfer cap %lx\n", i, cap.local_name());
+ Native_capability rcap = clients[i]->test_cap_reply(cap);
+ printf("got from server on CPU %u - received cap %lx\n", i, rcap.local_name());
+ }
+
+ printf("done\n");
+
+ sleep_forever();
+}
diff --git a/base/src/test/mp_server/target.mk b/base/src/test/mp_server/target.mk
new file mode 100644
index 0000000000..6661ff4503
--- /dev/null
+++ b/base/src/test/mp_server/target.mk
@@ -0,0 +1,3 @@
+TARGET = test-server-mp
+SRC_CC = main.cc
+LIBS = base
diff --git a/tool/autopilot.list b/tool/autopilot.list
index b0e0b38ca2..22943b6a9c 100644
--- a/tool/autopilot.list
+++ b/tool/autopilot.list
@@ -26,3 +26,4 @@ l4linux_netperf_usb30
l4linux_netperf_bridge
noux_tool_chain_auto
affinity
+mp_server