diff --git a/repos/base/include/topo_session/capability.h b/repos/base/include/topo_session/capability.h
new file mode 100644
index 0000000000..17f7a1a01b
--- /dev/null
+++ b/repos/base/include/topo_session/capability.h
@@ -0,0 +1,22 @@
+/*
+ * \brief Topo-session capability type
+ * \author Michael Müller
+ * \date 2022-10-06
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalanOS, witch is based on Genode OS framework
+ * distributed under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace Genode
+{
+ typedef Capability Topo_session_capability;
+} // namespace Genode
\ No newline at end of file
diff --git a/repos/base/include/topo_session/client.h b/repos/base/include/topo_session/client.h
new file mode 100644
index 0000000000..e4244a4820
--- /dev/null
+++ b/repos/base/include/topo_session/client.h
@@ -0,0 +1,40 @@
+/*
+ * \brief Client-side topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+
+namespace Genode {
+ struct Topo_session_client;
+ struct Node;
+}
+
+struct Genode::Topo_session_client : Rpc_client
+{
+ explicit Topo_session_client(Topo_session_capability session)
+ : Rpc_client(session) { }
+
+ Node *node_affinity_of(Affinity::Location &loc) override {
+ return call(loc);
+ }
+
+ unsigned node_count() override {
+ return call();
+ }
+};
\ No newline at end of file
diff --git a/repos/base/include/topo_session/connection.h b/repos/base/include/topo_session/connection.h
new file mode 100644
index 0000000000..556a96577c
--- /dev/null
+++ b/repos/base/include/topo_session/connection.h
@@ -0,0 +1,46 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+namespace Genode {
+ struct Topo_connection;
+}
+
+struct Genode::Topo_connection : Connection, Topo_session_client
+{
+ enum
+ {
+ RAM_QUOTA = 8192
+ };
+
+ Topo_connection(Env &env, const char *label = "", Affinity const &affinity = Affinity())
+ :
+ Connection(env,
+ session(env.parent(), affinity, "ram_quota=%u, cap_quota=%u, label=\"%s\"", RAM_QUOTA, CAP_QUOTA, label)),
+ Topo_session_client(cap()) {}
+
+ Node *node_affinity_of(Affinity::Location &loc) override {
+ return Topo_session_client::node_affinity_of(loc);
+ }
+
+ unsigned node_count() override {
+ return Topo_session_client::node_count();
+ }
+};
\ No newline at end of file
diff --git a/repos/base/include/topo_session/node.h b/repos/base/include/topo_session/node.h
new file mode 100644
index 0000000000..0d03bf865d
--- /dev/null
+++ b/repos/base/include/topo_session/node.h
@@ -0,0 +1,42 @@
+/*
+ * \brief Representation of a NUMA node
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+
+namespace Genode {
+ struct Node;
+}
+
+struct Genode::Node : List::Element
+{
+ /* ID presented to component */
+ unsigned _id;
+
+ unsigned _core_count;
+ List neighbours;
+
+ /* Physical NUMA node ID */
+ unsigned _native_id;
+
+ Node(unsigned id, unsigned native_id) : _id(id), _core_count(0), neighbours(), _native_id(native_id) {}
+
+ unsigned native_id() { return _native_id; }
+ unsigned id() { return _id; }
+ unsigned core_count() { return _core_count; }
+ void core_count(unsigned count) { _core_count = count; }
+ void increment_core_count() { _core_count++; }
+};
\ No newline at end of file
diff --git a/repos/base/include/topo_session/topo_session.h b/repos/base/include/topo_session/topo_session.h
new file mode 100644
index 0000000000..2bfda57d0b
--- /dev/null
+++ b/repos/base/include/topo_session/topo_session.h
@@ -0,0 +1,52 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+#include
+
+namespace Genode {
+
+ struct Topo_session;
+ struct Topo_session_client;
+ struct Node;
+}
+
+struct Genode::Topo_session : Session
+{
+ /**
+ * \nooapi
+ *
+ */
+ static const char *service_name() { return "TOPO"; }
+
+ enum
+ {
+ CAP_QUOTA = 2
+ };
+
+ typedef Topo_session_client Client;
+
+ virtual ~Topo_session() { }
+
+ virtual Node *node_affinity_of(Affinity::Location &) = 0;
+ virtual unsigned node_count() = 0;
+
+ GENODE_RPC(Rpc_node_affinity, Node*, node_affinity_of, Affinity::Location &);
+ GENODE_RPC(Rpc_node_count, unsigned, node_count);
+
+ GENODE_RPC_INTERFACE(Rpc_node_affinity, Rpc_node_count);
+};
\ No newline at end of file
diff --git a/repos/base/src/core/include/topo_root.h b/repos/base/src/core/include/topo_root.h
new file mode 100644
index 0000000000..9c7c5978b7
--- /dev/null
+++ b/repos/base/src/core/include/topo_root.h
@@ -0,0 +1,67 @@
+/*
+ * \brief Topology service root component
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+#include
+
+#include
+
+namespace Genode {
+
+ class Topo_root : public Root_component
+ {
+ private:
+ Ram_allocator &_ram_alloc;
+ Region_map &_local_rm;
+
+ protected:
+
+ Topo_session_component *_create_session(char const *args, Affinity const &affinity) override {
+ size_t ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0);
+
+ if (ram_quota < Trace::Control_area::SIZE)
+ throw Insufficient_ram_quota();
+
+ if (!affinity.valid())
+ throw Service_denied();
+
+ return new (md_alloc())
+ Topo_session_component(*this->ep(),
+ session_resources_from_args(args),
+ session_label_from_args(args),
+ session_diag_from_args(args),
+ _ram_alloc, _local_rm,
+ const_cast(affinity));
+ }
+
+ void _upgrade_session(Topo_session_component *topo, const char *args) override
+ {
+ topo->upgrade(ram_quota_from_args(args));
+ topo->upgrade(cap_quota_from_args(args));
+ }
+
+ public:
+
+ Topo_root(Ram_allocator &ram_alloc,
+ Region_map &local_rm,
+ Rpc_entrypoint &session_ep,
+ Allocator &md_alloc)
+ :
+ Root_component(&session_ep, &md_alloc),
+ _ram_alloc(ram_alloc), _local_rm(local_rm)
+ { }
+ };
+}
\ No newline at end of file
diff --git a/repos/base/src/core/include/topo_session_component.h b/repos/base/src/core/include/topo_session_component.h
new file mode 100644
index 0000000000..65b31bb243
--- /dev/null
+++ b/repos/base/src/core/include/topo_session_component.h
@@ -0,0 +1,61 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+
+#pragma once
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+
+namespace Genode {
+ class Topo_session_component;
+}
+
+class Genode::Topo_session_component : public Session_object
+{
+ private:
+ Genode::Affinity &_affinity;
+ Sliced_heap _md_alloc;
+
+ Node ***_node_affinities;
+ unsigned _node_count;
+
+ public:
+ Topo_session_component(Rpc_entrypoint &session_ep,
+ Resources const &resources,
+ Label const &label,
+ Diag const &diag,
+ Ram_allocator &ram_alloc,
+ Region_map &local_rm,
+ Affinity &affinity
+ );
+
+ /**
+ * @brief Topology session interface
+ */
+
+ Node *node_affinity_of(Affinity::Location &loc) override
+ {
+ return _node_affinities[loc.xpos()][loc.ypos()];
+ }
+
+ unsigned node_count() override
+ {
+ return _node_count;
+ }
+};
\ No newline at end of file
diff --git a/repos/base/src/core/topo_session_component.cc b/repos/base/src/core/topo_session_component.cc
new file mode 100644
index 0000000000..2bb8fb8b3e
--- /dev/null
+++ b/repos/base/src/core/topo_session_component.cc
@@ -0,0 +1,58 @@
+/*
+ * \brief Topology session interface
+ * \author Michael Müller
+ * \date 2022-10-06
+ *
+ * A topology session stores the component's view on the hardware topology, i.e. it's location within the NUMA topology.
+ */
+
+/*
+ * Copyright (C) 2022 Michael Müller
+ *
+ * This file is part of EalánOS which is based on the Genode OS framework
+ * released under the terms of the GNU Affero General Public License version 3.
+ */
+#include
+#include
+#include
+
+using namespace Genode;
+
+Topo_session_component::Topo_session_component(Rpc_entrypoint &session_ep,
+ Resources const &resources,
+ Label const &label,
+ Diag const &diag,
+ Ram_allocator &ram_alloc,
+ Region_map &local_rm,
+ Affinity &affinity)
+:
+ Session_object(session_ep, resources, label, diag),
+ _md_alloc(ram_alloc, local_rm),
+ _affinity(affinity)
+{
+ const unsigned height = affinity.space().height();
+ unsigned width = affinity.space().width();
+ unsigned curr_node_id = 0;
+ Node *node_created[] = new (_md_alloc) Node *[64]();
+
+ _node_affinities = new (_md_alloc) Node **[width];
+
+
+ for (unsigned x = 0; x < width; x++) {
+ _node_affinities[x] = new (_md_alloc) Node *[height];
+ for (unsigned y = 0; y < height; y++) {
+
+ Affinity::Location loc = Affinity::Location(x, y);
+ unsigned cpu_id = platform_specific().kernel_cpu_id(loc);
+ unsigned native_id = platform_specific().domain_of_cpu(cpu_id);
+
+ if (!node_created[node_id]) {
+ _node_affinities[x][y] = new (_md_alloc) Node(curr_node_id, native_id);
+ _node_affinities[x][y]->increment_core_count();
+ _node_count++;
+ } else {
+ (_node_affinities[x][y] = node_created[native_id])->increment_core_count();
+ }
+ }
+ }
+}