From dd0c8b10dc798cdeab9842c5a4e1cddc22310f64 Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Mon, 8 Dec 2025 18:38:02 +0100 Subject: [PATCH] Added support for habitats. --- .../include/spec/64bit/tukija/syscalls.h | 10 ++- .../include/tukija/syscall-generic.h | 70 +++++++++++++------ .../src/core/include/cell_component.h | 5 +- .../core/include/habitat_session_component.h | 45 ++++++++++-- repos/base/include/base/affinity.h | 7 ++ 5 files changed, 105 insertions(+), 32 deletions(-) diff --git a/repos/base-tukija/include/spec/64bit/tukija/syscalls.h b/repos/base-tukija/include/spec/64bit/tukija/syscalls.h index 41b344e2c8..b9ca6acb35 100644 --- a/repos/base-tukija/include/spec/64bit/tukija/syscalls.h +++ b/repos/base-tukija/include/spec/64bit/tukija/syscalls.h @@ -298,9 +298,15 @@ namespace Tukija { ALWAYS_INLINE - inline uint8_t create_cell(mword_t pd, uint8_t prio, mword_t &cip, mword_t &dst) + inline uint8_t create_cell(mword_t pd, mword_t hsel, uint8_t prio, mword_t &cip, mword_t &dst) { - return syscall_5(TUKIJA_CREATE_CELL, prio, pd, dst, cip); + return syscall_5(TUKIJA_CREATE_CELL, prio, pd, hsel, dst, cip); + } + + ALWAYS_INLINE + inline uint8_t create_habitat(mword_t sel, mword_t dst) + { + return syscall_1(TUKIJA_CREATE_HABITAT, 0, sel, dst); } ALWAYS_INLINE diff --git a/repos/base-tukija/include/tukija/syscall-generic.h b/repos/base-tukija/include/tukija/syscall-generic.h index 7e8dd6e37f..a891219a29 100644 --- a/repos/base-tukija/include/tukija/syscall-generic.h +++ b/repos/base-tukija/include/tukija/syscall-generic.h @@ -57,27 +57,28 @@ namespace Tukija { * NOVA system-call IDs */ enum Syscall { - NOVA_CALL = 0x0, - NOVA_REPLY = 0x1, - NOVA_CREATE_PD = 0x2, - NOVA_CREATE_EC = 0x3, - NOVA_CREATE_SC = 0x4, - NOVA_CREATE_PT = 0x5, - NOVA_CREATE_SM = 0x6, - NOVA_REVOKE = 0x7, - NOVA_MISC = 0x8, /* lookup, delegate, acpi_suspend */ - NOVA_EC_CTRL = 0x9, - NOVA_SC_CTRL = 0xa, - NOVA_PT_CTRL = 0xb, - NOVA_SM_CTRL = 0xc, - NOVA_ASSIGN_PCI = 0xd, - NOVA_ASSIGN_GSI = 0xe, - NOVA_PD_CTRL = 0xf, - TUKIJA_CREATE_CELL = 0x10, - TUKIJA_ALLOCATE = 0x11, - TUKIJA_CELL_CTRL = 0x12, - TUKIJA_RELEASE = 0x13, - TUKIJA_MAP_TIP = 0x14 + NOVA_CALL = 0x0, + NOVA_REPLY = 0x1, + NOVA_CREATE_PD = 0x2, + NOVA_CREATE_EC = 0x3, + NOVA_CREATE_SC = 0x4, + NOVA_CREATE_PT = 0x5, + NOVA_CREATE_SM = 0x6, + NOVA_REVOKE = 0x7, + NOVA_MISC = 0x8, /* lookup, delegate, acpi_suspend */ + NOVA_EC_CTRL = 0x9, + NOVA_SC_CTRL = 0xa, + NOVA_PT_CTRL = 0xb, + NOVA_SM_CTRL = 0xc, + NOVA_ASSIGN_PCI = 0xd, + NOVA_ASSIGN_GSI = 0xe, + NOVA_PD_CTRL = 0xf, + TUKIJA_CREATE_CELL = 0x10, + TUKIJA_ALLOCATE = 0x11, + TUKIJA_CELL_CTRL = 0x12, + TUKIJA_RELEASE = 0x13, + TUKIJA_MAP_TIP = 0x14, + TUKIJA_CREATE_HABITAT = 0x15 }; /** @@ -136,7 +137,11 @@ namespace Tukija { inline mword_t bit_cpu(unsigned const cpu) const { return cpu % CPUS_PER_VALUE; } - + + inline mword_t values() + { + return sizeof(raw) / sizeof(raw[0]); + } public: inline explicit Cpuset(mword_t const v) { @@ -183,6 +188,16 @@ namespace Tukija { } } + unsigned first_cpu() + { + long cpu = -1; + for (unsigned i = 0; i < values(); i++) { + cpu = bit_scan_forward(raw[i]); + if (cpu != -1) break; + } + return static_cast(cpu); + } + unsigned count() { unsigned count = 0; @@ -201,6 +216,17 @@ namespace Tukija { } }; + /** + * @brief Habitat Information page + * + */ + struct Habitat_info_page + { + alignas(64) Cpuset reserved_cores{0}; + alignas(64) Cpuset current_cores{0}; + alignas(64) bool resizable{false}; + }; + /** * Cell information pages * diff --git a/repos/base-tukija/src/core/include/cell_component.h b/repos/base-tukija/src/core/include/cell_component.h index 942beffc34..60ffd01367 100644 --- a/repos/base-tukija/src/core/include/cell_component.h +++ b/repos/base-tukija/src/core/include/cell_component.h @@ -15,6 +15,7 @@ #define _CORE__INCLUDE__CELL_COMPONENT_H_ /* Genode includes */ +#include "tukija/stdint.h" #include #include #include @@ -83,7 +84,7 @@ class Ealan::Cell_component : public Genode::Rpc_object, public: - Cell_component(Genode::Pd_session_capability pd_cap, Genode::uint16_t prio, Genode::Affinity &affinity, Genode::Rpc_entrypoint &ep, Genode::Region_map &rm, Genode::Session_label const &label, bool is_brick) : _ep(ep), _session_label(label), _rm(rm), _pd_cap(pd_cap), _pd(pd_cap), _native_pd(_pd.native_pd()), _is_brick(is_brick) { + Cell_component(Genode::Pd_session_capability pd_cap, Genode::uint16_t prio, Genode::Affinity &affinity, Genode::Rpc_entrypoint &ep, Genode::Region_map &rm, Genode::Session_label const &label, bool is_brick, Tukija::mword_t habitat_sel) : _ep(ep), _session_label(label), _rm(rm), _pd_cap(pd_cap), _pd(pd_cap), _native_pd(_pd.native_pd()), _is_brick(is_brick) { Tukija::mword_t cell_pd_sel = _native_pd.sel(); Tukija::mword_t cip_phys = 0; @@ -101,7 +102,7 @@ class Ealan::Cell_component : public Genode::Rpc_object, * a page frame for the CIP. The CIP will then be mapped by the kernel using the * supplied virtual address from the previously allocated region map. */ - if (Tukija::create_cell(cell_pd_sel, static_cast(prio), cip_phys, cip_virt)) { + if (Tukija::create_cell(cell_pd_sel, habitat_sel, static_cast(prio), cip_phys, cip_virt)) { Genode::error("Failed to create cell at Tukija."); throw Cell_creation_error(); } diff --git a/repos/base-tukija/src/core/include/habitat_session_component.h b/repos/base-tukija/src/core/include/habitat_session_component.h index 7e4414bd65..ead896df46 100644 --- a/repos/base-tukija/src/core/include/habitat_session_component.h +++ b/repos/base-tukija/src/core/include/habitat_session_component.h @@ -13,6 +13,13 @@ #ifndef _CORE__HABITAT_SESSION_COMPONENT_H_ #define _CORE__HABITAT_SESSION_COMPONENT_H_ +#include "base/ram_allocator.h" +#include "base/stdint.h" +#include "dataspace_component.h" +#include "platform_generic.h" +#include "region_map/region_map.h" +#include "tukija/stdint.h" +#include "tukija/syscall-generic.h" #include #include #include @@ -24,7 +31,7 @@ #include #include #include - +#include #include @@ -39,11 +46,15 @@ class Core::Habitat_session_component : public Genode::Session_object _managed_cells { }; + Genode::List _managed_cells{}; + Genode::addr_t _id_base; - void _calculate_mask_for_location(Tukija::Cpuset *coreset, const Genode::Affinity::Location &loc) + Genode::addr_t _sel() const { return _id_base; } + + + void _calculate_mask_for_location(Tukija::Cpuset *coreset, const Genode::Affinity::Space &space) { - const_cast(loc).for_each( + const_cast(space).for_each( [&](Genode::Affinity::Location const &location) { unsigned kernel_cpu = Core::platform_specific().kernel_cpu_id(location); @@ -52,11 +63,33 @@ class Core::Habitat_session_component : public Genode::Session_object(ep, resources, label, diag), _local_rm(rm), _affinity(affinity), _label(label), _ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()), _md_alloc(_ram_alloc, rm), _ep(ep) {} + + Habitat_session_component(Genode::Rpc_entrypoint &ep, + Genode::Session::Resources const &resources, + Genode::Session_label const &label, + Genode::Session::Diag const &diag, Genode::Ram_allocator &ram, + Genode::Region_map &rm, Genode::Affinity const &affinity) + : Genode::Session_object(ep, resources, label, diag), + _local_rm(rm), _affinity(affinity), _label(label), + _ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()), _md_alloc(_ram_alloc, rm), + _ep(ep), _id_base(cap_map().insert(1)) + { + Genode::log("Habitat's affinity is ", _affinity); + + Tukija::Habitat_info_page *haip; + Core::platform().region_alloc().alloc_aligned(Tukija::PAGE_SIZE_BYTE, Tukija::PAGE_SIZE_LOG2).with_result([&](void *ptr) { haip = static_cast(ptr); }, [&](Genode::Range_allocator::Alloc_error) { haip = nullptr; }); + + if (!haip) { Genode::error("Failed to allocate Habitat Info Page"); } + Tukija::create_habitat(_sel(), reinterpret_cast(haip)); + + _calculate_mask_for_location(&haip->reserved_cores, _affinity.space()); + + Genode::log("Created habitat: ", haip->reserved_cores); + } Ealan::Cell_capability create_cell(Genode::Capability pd_cap, [[maybe_unused]] Genode::Affinity &affinity, Genode::uint16_t prio, Genode::Session_label const &label, bool is_brick) override { - Ealan::Cell_component *cell = new (_md_alloc) Ealan::Cell_component(pd_cap, prio, affinity, _ep, _local_rm, label, is_brick); + Ealan::Cell_component *cell = new (_md_alloc) Ealan::Cell_component(pd_cap, prio, affinity, _ep, _local_rm, label, is_brick, _sel()); _managed_cells.insert(cell); diff --git a/repos/base/include/base/affinity.h b/repos/base/include/base/affinity.h index 821e72349e..adbdc31a07 100644 --- a/repos/base/include/base/affinity.h +++ b/repos/base/include/base/affinity.h @@ -93,6 +93,13 @@ class Genode::Affinity return Affinity::Space(node.attribute_value("width", 0U), node.attribute_value("height", 0U)); } + + template void for_each(const FUNC &f) + { + for (unsigned i = 0; i < total(); i++) { + f(location_of_index(i)); + } + } };