From 579b4833fb3f17b3a1e217ccd2731fe430cb27a4 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Tue, 11 Oct 2022 17:58:24 +0200 Subject: [PATCH] Introducing new topology service to query NUMA information from within a component. --- repos/base/include/topo_session/capability.h | 22 ++++++ repos/base/include/topo_session/client.h | 40 +++++++++++ repos/base/include/topo_session/connection.h | 46 +++++++++++++ repos/base/include/topo_session/node.h | 42 ++++++++++++ .../base/include/topo_session/topo_session.h | 52 ++++++++++++++ repos/base/src/core/include/topo_root.h | 67 +++++++++++++++++++ .../src/core/include/topo_session_component.h | 61 +++++++++++++++++ repos/base/src/core/topo_session_component.cc | 58 ++++++++++++++++ 8 files changed, 388 insertions(+) create mode 100644 repos/base/include/topo_session/capability.h create mode 100644 repos/base/include/topo_session/client.h create mode 100644 repos/base/include/topo_session/connection.h create mode 100644 repos/base/include/topo_session/node.h create mode 100644 repos/base/include/topo_session/topo_session.h create mode 100644 repos/base/src/core/include/topo_root.h create mode 100644 repos/base/src/core/include/topo_session_component.h create mode 100644 repos/base/src/core/topo_session_component.cc 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(); + } + } + } +}