From 63d6827f1673dab2512762a93bf3dee96e7108ed Mon Sep 17 00:00:00 2001 From: Michael Mueller Date: Thu, 20 Oct 2022 17:00:30 +0200 Subject: [PATCH] core: Added interface to allocate memory from a given NUMA region. --- repos/base/include/pd_session/client.h | 5 ++ repos/base/include/pd_session/pd_session.h | 8 ++- .../src/core/include/pd_session_component.h | 2 + repos/base/src/core/pd_session_component.cc | 52 +++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/repos/base/include/pd_session/client.h b/repos/base/include/pd_session/client.h index e578f192cd..9ee05e3700 100644 --- a/repos/base/include/pd_session/client.h +++ b/repos/base/include/pd_session/client.h @@ -77,6 +77,11 @@ struct Genode::Pd_session_client : Rpc_client { return call(size, cache); } + + Alloc_result try_alloc(size_t size, Ram_allocator::Numa_id numa_id, Cache cache = CACHED) override + { + return call(size, numa_id, cache); + } void free(Ram_dataspace_capability ds) override { call(ds); } diff --git a/repos/base/include/pd_session/pd_session.h b/repos/base/include/pd_session/pd_session.h index 9f6c7871c4..c6baa209e5 100644 --- a/repos/base/include/pd_session/pd_session.h +++ b/repos/base/include/pd_session/pd_session.h @@ -284,6 +284,11 @@ struct Genode::Pd_session : Session, Ram_allocator */ Ram_quota avail_ram() const { return { ram_quota().value - used_ram().value }; } + /** + * \brief Create new dataspace factory for given NUMA node + * \param + */ + /***************************************** ** Access to kernel-specific interface ** @@ -381,6 +386,7 @@ struct Genode::Pd_session : Session, Ram_allocator GENODE_RPC(Rpc_used_caps, Cap_quota, used_caps); GENODE_RPC(Rpc_try_alloc, Alloc_result, try_alloc, size_t, Cache); + GENODE_RPC(Rpc_try_alloc_numa, Alloc_result, try_alloc, size_t, Ram_allocator::Numa_id, Cache); GENODE_RPC(Rpc_free, void, free, Ram_dataspace_capability); GENODE_RPC_THROW(Rpc_transfer_ram_quota, void, transfer_quota, GENODE_TYPE_LIST(Out_of_ram, Invalid_session, Undefined_ref_account), @@ -402,7 +408,7 @@ struct Genode::Pd_session : Session, Ram_allocator Rpc_alloc_rpc_cap, Rpc_free_rpc_cap, Rpc_address_space, Rpc_stack_area, Rpc_linker_area, Rpc_ref_account, Rpc_transfer_cap_quota, Rpc_cap_quota, Rpc_used_caps, - Rpc_try_alloc, Rpc_free, + Rpc_try_alloc, Rpc_try_alloc_numa, Rpc_free, Rpc_transfer_ram_quota, Rpc_ram_quota, Rpc_used_ram, Rpc_native_pd, Rpc_managing_system, Rpc_dma_addr, Rpc_attach_dma); diff --git a/repos/base/src/core/include/pd_session_component.h b/repos/base/src/core/include/pd_session_component.h index 1b84ba015a..182ec8a1f5 100644 --- a/repos/base/src/core/include/pd_session_component.h +++ b/repos/base/src/core/include/pd_session_component.h @@ -318,6 +318,8 @@ class Genode::Pd_session_component : public Session_object Alloc_result try_alloc(size_t, Cache) override; + Alloc_result try_alloc(size_t, Ram_allocator::Numa_id, Cache) override; + void free(Ram_dataspace_capability) override; size_t dataspace_size(Ram_dataspace_capability) const override; diff --git a/repos/base/src/core/pd_session_component.cc b/repos/base/src/core/pd_session_component.cc index acc607aed4..87eff1d5de 100644 --- a/repos/base/src/core/pd_session_component.cc +++ b/repos/base/src/core/pd_session_component.cc @@ -73,6 +73,58 @@ Pd_session_component::try_alloc(size_t ds_size, Cache cache) ); } +Ram_allocator::Alloc_result +Pd_session_component::try_alloc(size_t ds_size, Ram_allocator::Numa_id numa_id, Cache cache) +{ + /* zero-sized dataspaces are not allowed */ + if (!ds_size) + return Alloc_error::DENIED; + + /* dataspace allocation granularity is page size */ + ds_size = align_addr(ds_size, 12); + + using Result = Ram_allocator::Alloc_result; + using Reservation = Genode::Reservation; + + /* track quota use */ + return _ram_quota_guard().with_reservation(Ram_quota{ds_size}, + + [&] (Reservation &ram_reservation) -> Result { + + /* + * In the worst case, we need to allocate a new slab block for + * the meta data of the dataspace to be created. Therefore, we + * temporarily withdraw the slab block size here to trigger an + * exception if the account does not have enough room for the meta + * data. + */ + Ram_quota const overhead { Ram_dataspace_factory::SLAB_BLOCK_SIZE }; + + if (!_ram_quota_guard().have_avail(overhead)) { + ram_reservation.cancel(); + return Ram_allocator::Alloc_error::OUT_OF_RAM; + } + + /* + * Each dataspace is an RPC object and thereby consumes a + * capability. + */ + return _cap_quota_guard().with_reservation(Cap_quota{1}, + + [&] (Genode::Reservation &) -> Result { + return _ram_ds_factory.try_alloc(ds_size, numa_id, cache); + }, + [&] () -> Result { + ram_reservation.cancel(); + return Ram_allocator::Alloc_error::OUT_OF_CAPS; + } + ); + }, + [&] () -> Result { + return Ram_allocator::Alloc_error::OUT_OF_RAM; + } + ); +} void Pd_session_component::free(Ram_dataspace_capability ds_cap) {