Introducing new topology service to query NUMA information from within a component.

This commit is contained in:
Michael Mueller
2022-10-11 17:58:24 +02:00
parent bdb1b222cd
commit 579b4833fb
8 changed files with 388 additions and 0 deletions

View File

@@ -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 <base/capability.h>
#include <topo_session/topo_session.h>
namespace Genode
{
typedef Capability<Topo_session> Topo_session_capability;
} // namespace Genode

View File

@@ -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 <topo_session/capability.h>
#include <topo_session/node.h>
#include <base/rpc_client.h>
#include <base/affinity.h>
namespace Genode {
struct Topo_session_client;
struct Node;
}
struct Genode::Topo_session_client : Rpc_client<Topo_session>
{
explicit Topo_session_client(Topo_session_capability session)
: Rpc_client<Topo_session>(session) { }
Node *node_affinity_of(Affinity::Location &loc) override {
return call<Rpc_node_affinity>(loc);
}
unsigned node_count() override {
return call<Rpc_node_count>();
}
};

View File

@@ -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 <topo_session/client.h>
#include <topo_session/node.h>
#include <base/connection.h>
namespace Genode {
struct Topo_connection;
}
struct Genode::Topo_connection : Connection<Topo_session>, Topo_session_client
{
enum
{
RAM_QUOTA = 8192
};
Topo_connection(Env &env, const char *label = "", Affinity const &affinity = Affinity())
:
Connection<Topo_session>(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();
}
};

View File

@@ -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 <util/list.h>
namespace Genode {
struct Node;
}
struct Genode::Node : List<Node>::Element
{
/* ID presented to component */
unsigned _id;
unsigned _core_count;
List<Node> 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++; }
};

View File

@@ -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 <session/session.h>
#include <base/affinity.h>
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);
};

View File

@@ -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 <root/component.h>
#include <topo_session_component.h>
namespace Genode {
class Topo_root : public Root_component<Topo_session_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&>(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<Topo_session_component>(&session_ep, &md_alloc),
_ram_alloc(ram_alloc), _local_rm(local_rm)
{ }
};
}

View File

@@ -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 <base/session_object.h>
#include <base/affinity.h>
#include <base/heap.h>
#include <topo_session/topo_session.h>
#include <topo_session/node.h>
namespace Genode {
class Topo_session_component;
}
class Genode::Topo_session_component : public Session_object<Topo_session>
{
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;
}
};

View File

@@ -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 <topo_session_component.h>
#include <platform_generic.h>
#include <platform.h>
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();
}
}
}
}