From 0d7d60a1f4e5c7ded3008005a2a03483b96f657c Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Thu, 13 Jun 2024 16:35:00 +0200 Subject: [PATCH] Remove exceptions from Pd_session interface This patch replaces exceptions of the PD session RPC interface with result types. The change of the quota-transfer RPC functions required the adaptation of base/quota_transfer.h and base/child.h. The 'alloc_signal_source' method has been renamed to 'signal_source' to avoid an exceedingly long name of the corresponding result type. The Pd_session::map function takes a 'Virt_range' instead of basic-type arguments. The 'Signal_source_capability' alias for 'Capability' has been removed. Issue #5245 --- .../core/spec/arm_v8/pd_session_support.cc | 5 +- .../core/spec/x86_64/pd_session_support.cc | 2 +- repos/base-hw/src/lib/base/signal_receiver.cc | 17 ++- .../base-linux/src/lib/base/rpc_cap_alloc.cc | 26 +++-- .../src/core/include/signal_broker.h | 9 +- .../base-nova/src/core/pd_session_support.cc | 10 +- repos/base/include/base/child.h | 11 +- repos/base/include/base/quota_transfer.h | 44 +++---- repos/base/include/base/service.h | 13 ++- repos/base/include/pd_session/client.h | 30 +++-- repos/base/include/pd_session/pd_session.h | 109 +++++++----------- .../src/core/include/pd_session_component.h | 43 ++++--- repos/base/src/core/include/signal_broker.h | 19 ++- repos/base/src/core/pd_session_component.cc | 62 +++++----- repos/base/src/core/pd_session_support.cc | 7 +- .../internal/expanding_pd_session_client.h | 28 +++-- .../src/include/signal_source/capability.h | 22 ---- repos/base/src/lib/base/rpc_cap_alloc.cc | 18 ++- repos/base/src/lib/base/signal.cc | 11 +- repos/os/src/driver/platform/device_pd.cc | 4 +- repos/os/src/lib/sandbox/service.h | 10 +- repos/os/src/monitor/inferior_pd.h | 14 +-- repos/os/src/monitor/monitored_pd.h | 36 +++--- repos/os/src/monitor/pd_intrinsics.h | 8 +- 24 files changed, 302 insertions(+), 256 deletions(-) delete mode 100644 repos/base/src/include/signal_source/capability.h diff --git a/repos/base-hw/src/core/spec/arm_v8/pd_session_support.cc b/repos/base-hw/src/core/spec/arm_v8/pd_session_support.cc index 9aae4f1799..3baffd243e 100644 --- a/repos/base-hw/src/core/spec/arm_v8/pd_session_support.cc +++ b/repos/base-hw/src/core/spec/arm_v8/pd_session_support.cc @@ -67,5 +67,8 @@ Capability System_control_component::control_cap(Aff bool Pd_session_component::assign_pci(addr_t, uint16_t) { return true; } -void Pd_session_component::map(addr_t, addr_t) { } +Pd_session::Map_result Pd_session_component::map(Pd_session::Virt_range) +{ + return Map_result::OK; +} diff --git a/repos/base-hw/src/core/spec/x86_64/pd_session_support.cc b/repos/base-hw/src/core/spec/x86_64/pd_session_support.cc index 952c80ef48..cd30c0d074 100644 --- a/repos/base-hw/src/core/spec/x86_64/pd_session_support.cc +++ b/repos/base-hw/src/core/spec/x86_64/pd_session_support.cc @@ -86,4 +86,4 @@ Capability System_control_component::control_cap(Aff bool Pd_session_component::assign_pci(addr_t, uint16_t) { return true; } -void Pd_session_component::map(addr_t, addr_t) { } +Pd_session::Map_result Pd_session_component::map(Pd_session::Virt_range) { return Map_result::OK; } diff --git a/repos/base-hw/src/lib/base/signal_receiver.cc b/repos/base-hw/src/lib/base/signal_receiver.cc index cf41e4dc63..e9c920efa7 100644 --- a/repos/base-hw/src/lib/base/signal_receiver.cc +++ b/repos/base-hw/src/lib/base/signal_receiver.cc @@ -57,12 +57,19 @@ Signal_receiver::Signal_receiver() : _pd(env().pd()) Ram_quota ram_upgrade { 0 }; Cap_quota cap_upgrade { 0 }; - try { - _cap = env().pd().alloc_signal_source(); + using Error = Pd_session::Signal_source_error; + + env().pd().signal_source().with_result( + [&] (Capability cap) { _cap = cap; }, + [&] (Error e) { + switch (e) { + case Error::OUT_OF_RAM: ram_upgrade = { 2*1024*sizeof(long) }; break; + case Error::OUT_OF_CAPS: cap_upgrade = { 4 }; break; + } + }); + + if (_cap.valid()) break; - } - catch (Out_of_ram) { ram_upgrade = Ram_quota { 2*1024*sizeof(long) }; } - catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; } env().upgrade(Parent::Env::pd(), String<100>("ram_quota=", ram_upgrade, ", " diff --git a/repos/base-linux/src/lib/base/rpc_cap_alloc.cc b/repos/base-linux/src/lib/base/rpc_cap_alloc.cc index 981624d4ff..044f942552 100644 --- a/repos/base-linux/src/lib/base/rpc_cap_alloc.cc +++ b/repos/base-linux/src/lib/base/rpc_cap_alloc.cc @@ -41,18 +41,26 @@ Native_capability Rpc_entrypoint::_alloc_rpc_cap(Pd_session& pd, Native_capabili { /* first we allocate a cap from core, to allow accounting of caps. */ for (;;) { - Ram_quota ram_upgrade { 0 }; - Cap_quota cap_upgrade { 0 }; - try { pd.alloc_rpc_cap(_cap); break; } - catch (Out_of_ram) { ram_upgrade = Ram_quota { 2*1024*sizeof(long) }; } - catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; } + Pd_session::Alloc_rpc_cap_result const result = pd.alloc_rpc_cap(_cap); + if (result.ok()) + break; - _parent().upgrade(Parent::Env::pd(), - String<100>("ram_quota=", ram_upgrade, ", " - "cap_quota=", cap_upgrade).string()); + using Error = Pd_session::Alloc_rpc_cap_error; + pd.alloc_rpc_cap(_cap).with_error([&] (Error e) { + + Ram_quota ram_upgrade { 0 }; + Cap_quota cap_upgrade { 0 }; + + switch (e) { + case Error::OUT_OF_RAM: ram_upgrade = { 2*1024*sizeof(long) }; break; + case Error::OUT_OF_CAPS: cap_upgrade = { 4 }; break; + } + _parent().upgrade(Parent::Env::pd(), + String<100>("ram_quota=", ram_upgrade, ", " + "cap_quota=", cap_upgrade).string()); + }); } - return Thread::native_thread().epoll.alloc_rpc_cap(); } diff --git a/repos/base-nova/src/core/include/signal_broker.h b/repos/base-nova/src/core/include/signal_broker.h index 89edffdbae..4d5892adb6 100644 --- a/repos/base-nova/src/core/include/signal_broker.h +++ b/repos/base-nova/src/core/include/signal_broker.h @@ -23,7 +23,6 @@ /* core includes */ #include #include -#include #include namespace Core { class Signal_broker; } @@ -38,7 +37,7 @@ class Core::Signal_broker Object_pool _obj_pool { }; Rpc_entrypoint &_context_ep; Signal_source_component _source; - Signal_source_capability _source_cap; + Capability _source_cap; Signal_context_slab _context_slab { _md_alloc }; public: @@ -66,15 +65,15 @@ class Core::Signal_broker free_context(reinterpret_cap_cast(r->cap())); } - Signal_source_capability alloc_signal_source() { return _source_cap; } + Capability alloc_signal_source() { return _source_cap; } - void free_signal_source(Signal_source_capability) { } + void free_signal_source(Capability) { } /* * \throw Allocator::Out_of_memory */ Signal_context_capability - alloc_context(Signal_source_capability, unsigned long imprint) + alloc_context(Capability, unsigned long imprint) { /* * XXX For now, we ignore the signal-source argument as we diff --git a/repos/base-nova/src/core/pd_session_support.cc b/repos/base-nova/src/core/pd_session_support.cc index 37d4a9e429..93b9df4e0f 100644 --- a/repos/base-nova/src/core/pd_session_support.cc +++ b/repos/base-nova/src/core/pd_session_support.cc @@ -43,7 +43,7 @@ bool Pd_session_component::assign_pci(addr_t pci_config_memory, uint16_t bdf) } -void Pd_session_component::map(addr_t virt, addr_t size) +Pd_session::Map_result Pd_session_component::map(Pd_session::Virt_range const virt_range) { Platform_pd &target_pd = *_pd; Nova::Utcb &utcb = *reinterpret_cast(Thread::myself()->utcb()); @@ -74,6 +74,8 @@ void Pd_session_component::map(addr_t virt, addr_t size) } }; + addr_t virt = virt_range.start; + size_t size = virt_range.num_bytes; try { while (size) { @@ -98,9 +100,13 @@ void Pd_session_component::map(addr_t virt, addr_t size) [&] (Region_map_component &, Fault const &) { /* don't reflect */ } ); } - } catch (...) { + } + catch (Out_of_ram) { return Map_result::OUT_OF_RAM; } + catch (Out_of_caps) { return Map_result::OUT_OF_CAPS; } + catch (...) { error(__func__, " failed ", Hex(virt), "+", Hex(size)); } + return Map_result::OK; } diff --git a/repos/base/include/base/child.h b/repos/base/include/base/child.h index f1d216b211..641c89a9e6 100644 --- a/repos/base/include/base/child.h +++ b/repos/base/include/base/child.h @@ -538,13 +538,16 @@ class Genode::Child : protected Rpc_object, _child._try_construct_env_dependent_members(); } + using Transfer_ram_quota_result = Pd_session::Transfer_ram_quota_result; + using Transfer_cap_quota_result = Pd_session::Transfer_ram_quota_result; + /** * Service (Ram_transfer::Account) interface */ - void transfer(Pd_session_capability to, Ram_quota amount) override + Ram_transfer_result transfer(Pd_session_capability to, Ram_quota amount) override { Ram_transfer::Account &from = _service; - from.transfer(to, amount); + return from.transfer(to, amount); } /** @@ -559,10 +562,10 @@ class Genode::Child : protected Rpc_object, /** * Service (Cap_transfer::Account) interface */ - void transfer(Pd_session_capability to, Cap_quota amount) override + Cap_transfer_result transfer(Pd_session_capability to, Cap_quota amount) override { Cap_transfer::Account &from = _service; - from.transfer(to, amount); + return from.transfer(to, amount); } /** diff --git a/repos/base/include/base/quota_transfer.h b/repos/base/include/base/quota_transfer.h index 2832955948..50bac4d24a 100644 --- a/repos/base/include/base/quota_transfer.h +++ b/repos/base/include/base/quota_transfer.h @@ -19,10 +19,10 @@ namespace Genode { - template class Quota_transfer; + template class Quota_transfer; - typedef Quota_transfer Ram_transfer; - typedef Quota_transfer Cap_transfer; + using Ram_transfer = Quota_transfer; + using Cap_transfer = Quota_transfer; } @@ -38,15 +38,15 @@ namespace Genode { * exception), the destructor the transfer object reverts the transfer in * flight. */ -template +template class Genode::Quota_transfer { public: - class Quota_exceeded : Exception { }; - struct Account : Noncopyable, Interface { + using Transfer_result = RESULT; + /** * Return capability used for transfers to the account * @@ -61,13 +61,11 @@ class Genode::Quota_transfer /** * Transfer quota to the specified account - * - * \throw Out_of_ram - * \throw Out_of_caps - * \throw Invalid_session - * \throw Undefined_ref_account */ - virtual void transfer(Capability, UNIT) { } + virtual Transfer_result transfer(Capability, UNIT) + { + return Transfer_result::OK; + } /** * Try to transfer quota, ignoring possible exceptions @@ -76,7 +74,7 @@ class Genode::Quota_transfer */ void try_transfer(Capability to, UNIT amount) { - try { transfer(to, amount); } catch (...) { } + transfer(to, amount); } }; @@ -93,9 +91,12 @@ class Genode::Quota_transfer Capability cap(UNIT) const override { return _cap; } - void transfer(Capability to, UNIT amount) override + using Transfer_result = RESULT; + + Transfer_result transfer(Capability to, UNIT amount) override { - if (to.valid()) _session.transfer_quota(to, amount); + return to.valid() ? _session.transfer_quota(to, amount) + : Transfer_result::OK; } }; @@ -106,14 +107,20 @@ class Genode::Quota_transfer Account &_from; Account &_to; + static bool _exceeded(Ram_quota, RESULT r) { return (r == RESULT::OUT_OF_RAM); } + static bool _exceeded(Cap_quota, RESULT r) { return (r == RESULT::OUT_OF_CAPS); } + public: + class Quota_exceeded : Exception { }; + /** * Constructor * * \param amount amount of quota to transfer * \param from donor account * \param to receiving account + * \throw Quota_exceeded */ Quota_transfer(UNIT amount, Account &from, Account &to) : @@ -122,11 +129,8 @@ class Genode::Quota_transfer if (!_from.cap(UNIT()).valid() || !_to.cap(UNIT()).valid()) return; - try { _from.transfer(_to.cap(UNIT()), amount); } - catch (typename SESSION::Undefined_ref_account) { } - catch (typename SESSION::Invalid_session) { } - catch (... /* 'Out_of_ram' / 'Out_of_caps' */) { - throw Quota_exceeded(); } + if (_exceeded(UNIT{}, _from.transfer(_to.cap(UNIT()), amount))) + throw Quota_exceeded(); } /** diff --git a/repos/base/include/base/service.h b/repos/base/include/base/service.h index 1c1d4d991a..77856fb289 100644 --- a/repos/base/include/base/service.h +++ b/repos/base/include/base/service.h @@ -41,6 +41,9 @@ class Genode::Service : public Ram_transfer::Account, typedef Session_state::Name Name; + using Ram_transfer_result = Ram_transfer::Account::Transfer_result; + using Cap_transfer_result = Cap_transfer::Account::Transfer_result; + private: Name const _name; @@ -473,9 +476,10 @@ class Genode::Child_service : public Async_service /** * Ram_transfer::Account interface */ - void transfer(Pd_session_capability to, Ram_quota amount) override + Ram_transfer_result transfer(Pd_session_capability to, Ram_quota amount) override { - if (to.valid()) _pd.transfer_quota(to, amount); + return to.valid() ? _pd.transfer_quota(to, amount) + : Ram_transfer_result::OK; } /** @@ -486,9 +490,10 @@ class Genode::Child_service : public Async_service /** * Cap_transfer::Account interface */ - void transfer(Pd_session_capability to, Cap_quota amount) override + Cap_transfer_result transfer(Pd_session_capability to, Cap_quota amount) override { - if (to.valid()) _pd.transfer_quota(to, amount); + return to.valid() ? _pd.transfer_quota(to, amount) + : Cap_transfer_result::OK; } /** diff --git a/repos/base/include/pd_session/client.h b/repos/base/include/pd_session/client.h index 70a8006409..5c8007d10a 100644 --- a/repos/base/include/pd_session/client.h +++ b/repos/base/include/pd_session/client.h @@ -31,15 +31,15 @@ struct Genode::Pd_session_client : Rpc_client bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) override { return call(pci_config_memory_address, bdf); } - void map(addr_t virt, addr_t size) override { call(virt, size); } + Map_result map(Virt_range range) override { return call(range); } - Signal_source_capability alloc_signal_source() override { - return call(); } + Signal_source_result signal_source() override { + return call(); } - void free_signal_source(Signal_source_capability cap) override { + void free_signal_source(Capability cap) override { call(cap); } - Alloc_context_result alloc_context(Signal_source_capability source, + Alloc_context_result alloc_context(Capability source, Imprint imprint) override { return call(source, imprint); } @@ -49,7 +49,7 @@ struct Genode::Pd_session_client : Rpc_client void submit(Signal_context_capability receiver, unsigned cnt = 1) override { call(receiver, cnt); } - Native_capability alloc_rpc_cap(Native_capability ep) override { + Alloc_rpc_cap_result alloc_rpc_cap(Native_capability ep) override { return call(ep); } void free_rpc_cap(Native_capability cap) override { @@ -64,11 +64,14 @@ struct Genode::Pd_session_client : Rpc_client Capability linker_area() override { return call(); } - void ref_account(Capability pd) override { - call(pd); } + Ref_account_result ref_account(Capability pd) override { + return call(pd); } - void transfer_quota(Capability pd, Cap_quota amount) override { - call(pd, amount); } + Transfer_cap_quota_result transfer_quota(Capability pd, + Cap_quota amount) override + { + return call(pd, amount); + } Cap_quota cap_quota() const override { return call(); } Cap_quota used_caps() const override { return call(); } @@ -85,8 +88,11 @@ struct Genode::Pd_session_client : Rpc_client return ds.valid() ? Dataspace_client(ds).size() : 0; } - void transfer_quota(Pd_session_capability pd_session, Ram_quota amount) override { - call(pd_session, amount); } + Transfer_ram_quota_result transfer_quota(Pd_session_capability pd_session, + Ram_quota amount) override + { + return call(pd_session, amount); + } Ram_quota ram_quota() const override { return call(); } Ram_quota used_ram() const override { return call(); } diff --git a/repos/base/include/pd_session/pd_session.h b/repos/base/include/pd_session/pd_session.h index 8b16b6f725..0e2072feaa 100644 --- a/repos/base/include/pd_session/pd_session.h +++ b/repos/base/include/pd_session/pd_session.h @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -71,48 +70,39 @@ struct Genode::Pd_session : Session, Ram_allocator */ virtual bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) = 0; + struct Virt_range { addr_t start; size_t num_bytes; }; + + enum class Map_result { OK, OUT_OF_RAM, OUT_OF_CAPS }; + /** - * Trigger eager insertion of page frames to page table within - * specified virtual range. + * Trigger eager population of page table within specified virtual range * * If the used kernel don't support this feature, the operation will * silently ignore the request. - * - * \param virt virtual address within the address space to start - * \param size the virtual size of the region - * - * \throw Out_of_ram - * \throw Out_of_caps */ - virtual void map(addr_t virt, addr_t size) = 0; + virtual Map_result map(Virt_range) = 0; + /******************************** ** Support for the signal API ** ********************************/ - typedef Capability Signal_source_capability; - - class Invalid_session : public Exception { }; - class Undefined_ref_account : public Exception { }; + enum class Signal_source_error { OUT_OF_RAM, OUT_OF_CAPS }; + using Signal_source_result = Attempt, Signal_source_error>; /** - * Create a new signal source - * - * \return a cap that acts as reference to the created source + * Return signal source for the PD * * The signal source provides an interface to wait for incoming signals. - * - * \throw Out_of_ram - * \throw Out_of_caps */ - virtual Signal_source_capability alloc_signal_source() = 0; + virtual Signal_source_result signal_source() = 0; /** * Free a signal source * * \param cap capability of the signal source to destroy */ - virtual void free_signal_source(Signal_source_capability cap) = 0; + virtual void free_signal_source(Capability cap) = 0; enum class Alloc_context_error { OUT_OF_RAM, OUT_OF_CAPS, INVALID_SIGNAL_SOURCE }; using Alloc_context_result = Attempt, Alloc_context_error>; @@ -128,7 +118,7 @@ struct Genode::Pd_session : Session, Ram_allocator * originating from the allocated signal-context capability * \return new signal-context capability */ - virtual Alloc_context_result alloc_context(Signal_source_capability source, + virtual Alloc_context_result alloc_context(Capability source, Imprint imprint) = 0; /** @@ -159,17 +149,17 @@ struct Genode::Pd_session : Session, Ram_allocator ** Support for the RPC framework ** ***********************************/ + enum class Alloc_rpc_cap_error { OUT_OF_RAM, OUT_OF_CAPS }; + using Alloc_rpc_cap_result = Attempt; + /** * Allocate new RPC-object capability * * \param ep entry point that will use this capability * - * \throw Out_of_ram if meta-data backing store is exhausted - * \throw Out_of_caps if 'cap_quota' is exceeded - * * \return new RPC capability */ - virtual Native_capability alloc_rpc_cap(Native_capability ep) = 0; + virtual Alloc_rpc_cap_result alloc_rpc_cap(Native_capability ep) = 0; /** * Free RPC-object capability @@ -205,12 +195,14 @@ struct Genode::Pd_session : Session, Ram_allocator ** Accounting for capability allocations ** *******************************************/ + enum class Ref_account_result { OK, INVALID_SESSION }; + /** * Define reference account for the PD session - * - * \throw Invalid_session */ - virtual void ref_account(Capability) = 0; + virtual Ref_account_result ref_account(Capability) = 0; + + enum class Transfer_cap_quota_result { OK, OUT_OF_CAPS, INVALID_SESSION, NO_REF_ACCOUNT }; /** * Transfer capability quota to another PD session @@ -218,14 +210,11 @@ struct Genode::Pd_session : Session, Ram_allocator * \param to receiver of quota donation * \param amount amount of quota to donate * - * \throw Out_of_caps - * \throw Invalid_session - * \throw Undefined_ref_account - * * Quota can only be transfered if the specified PD session is either the * reference account for this session or vice versa. */ - virtual void transfer_quota(Capability to, Cap_quota amount) = 0; + virtual Transfer_cap_quota_result transfer_quota(Capability to, + Cap_quota amount) = 0; /** * Return current capability-quota limit @@ -255,20 +244,19 @@ struct Genode::Pd_session : Session, Ram_allocator * which comprises the actual allocation and deallocation operations. */ + enum class Transfer_ram_quota_result { OK, OUT_OF_RAM, INVALID_SESSION, NO_REF_ACCOUNT }; + /** * Transfer quota to another RAM session * * \param to receiver of quota donation * \param amount amount of quota to donate * - * \throw Out_of_ram - * \throw Invalid_session - * \throw Undefined_ref_account - * * Quota can only be transfered if the specified PD session is either the * reference account for this session or vice versa. */ - virtual void transfer_quota(Capability to, Ram_quota amount) = 0; + virtual Transfer_ram_quota_result transfer_quota(Capability to, + Ram_quota amount) = 0; /** * Return current quota limit @@ -364,55 +352,38 @@ struct Genode::Pd_session : Session, Ram_allocator GENODE_RPC(Rpc_assign_parent, void, assign_parent, Capability); GENODE_RPC(Rpc_assign_pci, bool, assign_pci, addr_t, uint16_t); - GENODE_RPC_THROW(Rpc_map, void, map, - GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), - addr_t, addr_t); - - GENODE_RPC_THROW(Rpc_alloc_signal_source, Signal_source_capability, - alloc_signal_source, - GENODE_TYPE_LIST(Out_of_ram, Out_of_caps)); - GENODE_RPC(Rpc_free_signal_source, void, free_signal_source, Signal_source_capability); + GENODE_RPC(Rpc_map, Map_result, map, Virt_range); + GENODE_RPC(Rpc_signal_source, Signal_source_result, signal_source); + GENODE_RPC(Rpc_free_signal_source, void, free_signal_source, Capability); GENODE_RPC(Rpc_alloc_context, Alloc_context_result, alloc_context, - Signal_source_capability, Imprint); - GENODE_RPC(Rpc_free_context, void, free_context, - Capability); + Capability, Imprint); + GENODE_RPC(Rpc_free_context, void, free_context, Capability); GENODE_RPC(Rpc_submit, void, submit, Capability, unsigned); - - GENODE_RPC_THROW(Rpc_alloc_rpc_cap, Native_capability, alloc_rpc_cap, - GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), Native_capability); + GENODE_RPC(Rpc_alloc_rpc_cap, Alloc_rpc_cap_result, alloc_rpc_cap, Native_capability); GENODE_RPC(Rpc_free_rpc_cap, void, free_rpc_cap, Native_capability); - GENODE_RPC(Rpc_address_space, Capability, address_space); GENODE_RPC(Rpc_stack_area, Capability, stack_area); GENODE_RPC(Rpc_linker_area, Capability, linker_area); - - GENODE_RPC_THROW(Rpc_ref_account, void, ref_account, - GENODE_TYPE_LIST(Invalid_session), Capability); - GENODE_RPC_THROW(Rpc_transfer_cap_quota, void, transfer_quota, - GENODE_TYPE_LIST(Out_of_caps, Invalid_session, Undefined_ref_account), - Capability, Cap_quota); + GENODE_RPC(Rpc_ref_account, Ref_account_result, ref_account, Capability); + GENODE_RPC(Rpc_transfer_cap_quota, Transfer_cap_quota_result, transfer_quota, + Capability, Cap_quota); GENODE_RPC(Rpc_cap_quota, Cap_quota, cap_quota); GENODE_RPC(Rpc_used_caps, Cap_quota, used_caps); - GENODE_RPC(Rpc_try_alloc, Alloc_result, try_alloc, size_t, 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), - Capability, Ram_quota); + GENODE_RPC(Rpc_transfer_ram_quota, Transfer_ram_quota_result, transfer_quota, + Capability, Ram_quota); GENODE_RPC(Rpc_ram_quota, Ram_quota, ram_quota); GENODE_RPC(Rpc_used_ram, Ram_quota, used_ram); - GENODE_RPC(Rpc_native_pd, Capability, native_pd); - GENODE_RPC(Rpc_system_control_cap, Capability, system_control_cap, Affinity::Location); - GENODE_RPC(Rpc_dma_addr, addr_t, dma_addr, Ram_dataspace_capability); GENODE_RPC(Rpc_attach_dma, Attach_dma_result, attach_dma, Dataspace_capability, addr_t); GENODE_RPC_INTERFACE(Rpc_assign_parent, Rpc_assign_pci, Rpc_map, - Rpc_alloc_signal_source, Rpc_free_signal_source, + Rpc_signal_source, Rpc_free_signal_source, Rpc_alloc_context, Rpc_free_context, Rpc_submit, Rpc_alloc_rpc_cap, Rpc_free_rpc_cap, Rpc_address_space, Rpc_stack_area, Rpc_linker_area, Rpc_ref_account, diff --git a/repos/base/src/core/include/pd_session_component.h b/repos/base/src/core/include/pd_session_component.h index 58a5821dd8..370b1c85f2 100644 --- a/repos/base/src/core/include/pd_session_component.h +++ b/repos/base/src/core/include/pd_session_component.h @@ -198,24 +198,30 @@ class Core::Pd_session_component : public Session_object bool assign_pci(addr_t, uint16_t) override; - void map(addr_t, addr_t) override; + Map_result map(Pd_session::Virt_range) override; /**************** ** Signalling ** ****************/ - Signal_source_capability alloc_signal_source() override + Signal_source_result signal_source() override { - _consume_cap(SIG_SOURCE_CAP); + try { _consume_cap(SIG_SOURCE_CAP); } + catch (Out_of_caps) { + return Signal_source_error::OUT_OF_CAPS; } + + Signal_source_result result = Capability(); + try { return _signal_broker.alloc_signal_source(); } - catch (Allocator::Out_of_memory) { - _released_cap_silent(); - throw Out_of_ram(); - } + catch (Out_of_ram) { result = Signal_source_error::OUT_OF_RAM; } + catch (Out_of_caps) { result = Signal_source_error::OUT_OF_CAPS; } + + _released_cap_silent(); + return result; } - void free_signal_source(Signal_source_capability sig_rec_cap) override + void free_signal_source(Capability sig_rec_cap) override { if (sig_rec_cap.valid()) { _signal_broker.free_signal_source(sig_rec_cap); @@ -224,7 +230,7 @@ class Core::Pd_session_component : public Session_object } Alloc_context_result - alloc_context(Signal_source_capability sig_rec_cap, Imprint imprint) override + alloc_context(Capability sig_rec_cap, Imprint imprint) override { try { Cap_quota_guard::Reservation cap_costs(_cap_quota_guard(), Cap_quota{1}); @@ -257,14 +263,19 @@ class Core::Pd_session_component : public Session_object ** RPC capability allocation ** *******************************/ - Native_capability alloc_rpc_cap(Native_capability ep) override + Alloc_rpc_cap_result alloc_rpc_cap(Native_capability ep) override { /* may throw 'Out_of_caps' */ - _consume_cap(RPC_CAP); + try { _consume_cap(RPC_CAP); } + catch (Out_of_caps) { + return Alloc_rpc_cap_error::OUT_OF_CAPS; } /* may throw 'Out_of_ram' */ - try { return _rpc_cap_factory.alloc(ep); } - catch (...) { _released_cap_silent(); throw; } + try { + return _rpc_cap_factory.alloc(ep); } + catch (...) { + _released_cap_silent(); + return Alloc_rpc_cap_error::OUT_OF_RAM; } } void free_rpc_cap(Native_capability cap) override @@ -292,10 +303,10 @@ class Core::Pd_session_component : public Session_object ** Capability and RAM trading and accounting ** ***********************************************/ - void ref_account(Capability) override; + Ref_account_result ref_account(Capability) override; - void transfer_quota(Capability, Cap_quota) override; - void transfer_quota(Capability, Ram_quota) override; + Transfer_cap_quota_result transfer_quota(Capability, Cap_quota) override; + Transfer_ram_quota_result transfer_quota(Capability, Ram_quota) override; Cap_quota cap_quota() const override { diff --git a/repos/base/src/core/include/signal_broker.h b/repos/base/src/core/include/signal_broker.h index 0dda81655d..26d36cb60a 100644 --- a/repos/base/src/core/include/signal_broker.h +++ b/repos/base/src/core/include/signal_broker.h @@ -16,7 +16,6 @@ /* core includes */ #include -#include #include #include @@ -27,12 +26,12 @@ class Core::Signal_broker { private: - Allocator &_md_alloc; - Rpc_entrypoint &_source_ep; - Rpc_entrypoint &_context_ep; - Signal_source_component _source; - Signal_source_capability _source_cap; - Signal_context_slab _contexts_slab { _md_alloc }; + Allocator &_md_alloc; + Rpc_entrypoint &_source_ep; + Rpc_entrypoint &_context_ep; + Signal_source_component _source; + Capability _source_cap; + Signal_context_slab _contexts_slab { _md_alloc }; Signal_delivery_proxy_component _delivery_proxy { _source_ep }; public: @@ -60,12 +59,12 @@ class Core::Signal_broker free_context(r->cap()); } - Signal_source_capability alloc_signal_source() { return _source_cap; } + Capability alloc_signal_source() { return _source_cap; } - void free_signal_source(Signal_source_capability) { } + void free_signal_source(Capability) { } Signal_context_capability - alloc_context(Signal_source_capability, unsigned long imprint) + alloc_context(Capability, unsigned long imprint) { /* * XXX For now, we ignore the signal-source argument as we diff --git a/repos/base/src/core/pd_session_component.cc b/repos/base/src/core/pd_session_component.cc index 94984ec896..de43c03fdd 100644 --- a/repos/base/src/core/pd_session_component.cc +++ b/repos/base/src/core/pd_session_component.cc @@ -99,78 +99,88 @@ size_t Pd_session_component::dataspace_size(Ram_dataspace_capability ds_cap) con } -void Pd_session_component::ref_account(Capability pd_cap) +Pd_session::Ref_account_result Pd_session_component::ref_account(Capability pd_cap) { /* the reference account can be defined only once */ if (_cap_account.constructed()) - return; + return Ref_account_result::OK; if (this->cap() == pd_cap) - return; + return Ref_account_result::OK; + + Ref_account_result result = Ref_account_result::INVALID_SESSION; _ep.apply(pd_cap, [&] (Pd_session_component *pd) { - if (!pd || !pd->_ram_account.constructed()) { - error("invalid PD session specified as ref account"); - throw Invalid_session(); - } + if (!pd || !pd->_ram_account.constructed()) + return; _cap_account.construct(_cap_quota_guard(), _label, *pd->_cap_account); _ram_account.construct(_ram_quota_guard(), _label, *pd->_ram_account); + + result = Ref_account_result::OK; }); + return result; } -void Pd_session_component::transfer_quota(Capability pd_cap, - Cap_quota amount) +Pd_session::Transfer_cap_quota_result +Pd_session_component::transfer_quota(Capability pd_cap, Cap_quota amount) { if (!_cap_account.constructed()) - throw Undefined_ref_account(); + return Transfer_cap_quota_result::NO_REF_ACCOUNT; if (this->cap() == pd_cap) - return; + return Transfer_cap_quota_result::OK; + + Transfer_cap_quota_result result = Transfer_cap_quota_result::INVALID_SESSION; _ep.apply(pd_cap, [&] (Pd_session_component *pd) { if (!pd || !pd->_cap_account.constructed()) - throw Invalid_session(); + return; try { _cap_account->transfer_quota(*pd->_cap_account, amount); diag("transferred ", amount, " caps " "to '", pd->_cap_account->label(), "' (", _cap_account, ")"); + result = Transfer_cap_quota_result::OK; } - catch (Account::Unrelated_account) { - warning("attempt to transfer cap quota to unrelated PD session"); - throw Invalid_session(); } + catch (Account::Unrelated_account) { } catch (Account::Limit_exceeded) { - throw Out_of_caps(); } + result = Transfer_cap_quota_result::OUT_OF_CAPS; + } }); + return result; } -void Pd_session_component::transfer_quota(Capability pd_cap, - Ram_quota amount) +Pd_session::Transfer_ram_quota_result +Pd_session_component::transfer_quota(Capability pd_cap, Ram_quota amount) { if (!_ram_account.constructed()) - throw Undefined_ref_account(); + return Transfer_ram_quota_result::NO_REF_ACCOUNT; if (this->cap() == pd_cap) - return; + return Transfer_ram_quota_result::OK; + + Transfer_ram_quota_result result = Transfer_ram_quota_result::INVALID_SESSION; _ep.apply(pd_cap, [&] (Pd_session_component *pd) { if (!pd || !pd->_ram_account.constructed()) - throw Invalid_session(); + return; try { - _ram_account->transfer_quota(*pd->_ram_account, amount); } - catch (Account::Unrelated_account) { - warning("attempt to transfer RAM quota to unrelated PD session"); - throw Invalid_session(); } + _ram_account->transfer_quota(*pd->_ram_account, amount); + result = Transfer_ram_quota_result::OK; + } + catch (Account::Unrelated_account) { } catch (Account::Limit_exceeded) { - throw Out_of_ram(); } + result = Transfer_ram_quota_result::OUT_OF_RAM; + } }); + return result; } diff --git a/repos/base/src/core/pd_session_support.cc b/repos/base/src/core/pd_session_support.cc index 26ede054e2..561566c060 100644 --- a/repos/base/src/core/pd_session_support.cc +++ b/repos/base/src/core/pd_session_support.cc @@ -18,9 +18,14 @@ using namespace Core; + bool Pd_session_component::assign_pci(addr_t, uint16_t) { return true; } -void Pd_session_component::map(addr_t, addr_t) { } + +Pd_session::Map_result Pd_session_component::map(Pd_session::Virt_range) +{ + return Map_result::OK; +} class System_control_dummy : public System_control diff --git a/repos/base/src/include/base/internal/expanding_pd_session_client.h b/repos/base/src/include/base/internal/expanding_pd_session_client.h index 836da9d353..fea7aa48fe 100644 --- a/repos/base/src/include/base/internal/expanding_pd_session_client.h +++ b/repos/base/src/include/base/internal/expanding_pd_session_client.h @@ -83,26 +83,30 @@ struct Genode::Expanding_pd_session_client : Pd_session_client } } - void transfer_quota(Pd_session_capability pd_session, Ram_quota amount) override + Transfer_ram_quota_result transfer_quota(Pd_session_capability pd_session, Ram_quota amount) override { /* * Should the transfer fail because we don't have enough quota, request * the needed amount from the parent. */ - enum { NUM_ATTEMPTS = 2 }; - retry( - [&] () { Pd_session_client::transfer_quota(pd_session, amount); }, - [&] () { _request_ram_from_parent(amount.value); }, - NUM_ATTEMPTS); + for (;;) { + auto const result = Pd_session_client::transfer_quota(pd_session, amount); + if (result != Transfer_ram_quota_result::OUT_OF_RAM) + return result; + + _request_ram_from_parent(amount.value); + } } - void transfer_quota(Pd_session_capability pd_session, Cap_quota amount) override + Transfer_cap_quota_result transfer_quota(Pd_session_capability pd_session, Cap_quota amount) override { - enum { NUM_ATTEMPTS = 2 }; - retry( - [&] () { Pd_session_client::transfer_quota(pd_session, amount); }, - [&] () { _request_caps_from_parent(amount.value); }, - NUM_ATTEMPTS); + for (;;) { + auto const result = Pd_session_client::transfer_quota(pd_session, amount); + if (result != Transfer_cap_quota_result::OUT_OF_CAPS) + return result; + + _request_caps_from_parent(amount.value); + } } }; diff --git a/repos/base/src/include/signal_source/capability.h b/repos/base/src/include/signal_source/capability.h deleted file mode 100644 index 0364ad7bc1..0000000000 --- a/repos/base/src/include/signal_source/capability.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief Signal-source capability type - * \author Norman Feske - * \date 2016-01-04 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__SIGNAL_SOURCE__CAPABILITY_H_ -#define _INCLUDE__SIGNAL_SOURCE__CAPABILITY_H_ - -#include -#include - -namespace Genode { typedef Capability Signal_source_capability; } - -#endif /* _INCLUDE__SIGNAL_SOURCE__CAPABILITY_H_ */ diff --git a/repos/base/src/lib/base/rpc_cap_alloc.cc b/repos/base/src/lib/base/rpc_cap_alloc.cc index 2ed5628e82..bf620ffa47 100644 --- a/repos/base/src/lib/base/rpc_cap_alloc.cc +++ b/repos/base/src/lib/base/rpc_cap_alloc.cc @@ -45,9 +45,21 @@ Native_capability Rpc_entrypoint::_alloc_rpc_cap(Pd_session &pd, Ram_quota ram_upgrade { 0 }; Cap_quota cap_upgrade { 0 }; - try { return pd.alloc_rpc_cap(_cap); } - catch (Out_of_ram) { ram_upgrade = Ram_quota { 2*1024*sizeof(long) }; } - catch (Out_of_caps) { cap_upgrade = Cap_quota { 4 }; } + using Error = Pd_session::Alloc_rpc_cap_error; + + Native_capability result { }; + + pd.alloc_rpc_cap(_cap).with_result( + [&] (Native_capability cap) { result = cap; }, + [&] (Error e) { + switch (e) { + case Error::OUT_OF_RAM: ram_upgrade = { 2*1024*sizeof(long) }; break; + case Error::OUT_OF_CAPS: cap_upgrade = { 4 }; break; + } + }); + + if (result.valid()) + return result; _parent().upgrade(Parent::Env::pd(), String<100>("ram_quota=", ram_upgrade, ", " diff --git a/repos/base/src/lib/base/signal.cc b/repos/base/src/lib/base/signal.cc index e9996cd425..2fbe929f29 100644 --- a/repos/base/src/lib/base/signal.cc +++ b/repos/base/src/lib/base/signal.cc @@ -46,12 +46,15 @@ class Signal_handler_thread : Thread, Blockade void entry() override { - _signal_source.construct(_cpu, _pd.alloc_signal_source()); - wakeup(); - Signal_receiver::dispatch_signals(*_signal_source); + _pd.signal_source().with_result([&] (Capability source) { + _signal_source.construct(_cpu, source); + wakeup(); + Signal_receiver::dispatch_signals(*_signal_source); }, + [&] (Pd_session::Signal_source_error) { + error("failed to initialize signal-source interface"); }); } - enum { STACK_SIZE = 4*1024*sizeof(addr_t) }; + static constexpr size_t STACK_SIZE = 4*1024*sizeof(addr_t); public: diff --git a/repos/os/src/driver/platform/device_pd.cc b/repos/os/src/driver/platform/device_pd.cc index 3d7ac2efbf..695ad6f6d0 100644 --- a/repos/os/src/driver/platform/device_pd.cc +++ b/repos/os/src/driver/platform/device_pd.cc @@ -83,7 +83,7 @@ void Device_pd::add_range(Io_mmu::Range const & range, _pd.attach_dma(cap, range.start).with_result( [&] (Pd_session::Attach_dma_ok) { /* trigger eager mapping of memory */ - _pd.map(range.start, range.size); + _pd.map(Pd_session::Virt_range { range.start, range.size }); retry = false; }, [&] (Pd_session::Attach_dma_error e) { @@ -123,7 +123,7 @@ void Device_pd::enable_pci_device(Io_mem_dataspace_capability const io_mem_cap, throw Region_map::Region_conflict(); /* trigger eager mapping of memory */ - _pd.map(addr, 0x1000); + _pd.map(Pd_session::Virt_range { addr, 0x1000 }); /* try to assign pci device to this protection domain */ if (!_pd.assign_pci(addr, Pci::Bdf::rid(bdf))) diff --git a/repos/os/src/lib/sandbox/service.h b/repos/os/src/lib/sandbox/service.h index 9589de91b5..f6e2899b54 100644 --- a/repos/os/src/lib/sandbox/service.h +++ b/repos/os/src/lib/sandbox/service.h @@ -118,9 +118,10 @@ class Sandbox::Routed_service : public Async_service, public Abandonable /** * Ram_transfer::Account interface */ - void transfer(Pd_session_capability to, Ram_quota amount) override + Ram_transfer_result transfer(Pd_session_capability to, Ram_quota amount) override { - if (to.valid()) _pd_accessor.pd().transfer_quota(to, amount); + return to.valid() ? _pd_accessor.pd().transfer_quota(to, amount) + : Ram_transfer_result::OK; } /** @@ -134,9 +135,10 @@ class Sandbox::Routed_service : public Async_service, public Abandonable /** * Cap_transfer::Account interface */ - void transfer(Pd_session_capability to, Cap_quota amount) override + Cap_transfer_result transfer(Pd_session_capability to, Cap_quota amount) override { - if (to.valid()) _pd_accessor.pd().transfer_quota(to, amount); + return to.valid() ? _pd_accessor.pd().transfer_quota(to, amount) + : Cap_transfer_result::OK; } /** diff --git a/repos/os/src/monitor/inferior_pd.h b/repos/os/src/monitor/inferior_pd.h index 3e25315082..4b3cc08cac 100644 --- a/repos/os/src/monitor/inferior_pd.h +++ b/repos/os/src/monitor/inferior_pd.h @@ -198,16 +198,16 @@ struct Monitor::Inferior_pd : Monitored_pd_session bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) override { return _real.call(pci_config_memory_address, bdf); } - void map(addr_t virt, addr_t size) override { - _real.call(virt, size); } + Map_result map(Virt_range range) override { + return _real.call(range); } - Signal_source_capability alloc_signal_source() override { - return _real.call(); } + Signal_source_result signal_source() override { + return _real.call(); } - void free_signal_source(Signal_source_capability cap) override { + void free_signal_source(Capability cap) override { _real.call(cap); } - Alloc_context_result alloc_context(Signal_source_capability source, + Alloc_context_result alloc_context(Capability source, Imprint imprint) override { return _real.call(source, imprint); } @@ -217,7 +217,7 @@ struct Monitor::Inferior_pd : Monitored_pd_session void submit(Signal_context_capability receiver, unsigned cnt = 1) override { _real.call(receiver, cnt); } - Native_capability alloc_rpc_cap(Native_capability ep) override { + Alloc_rpc_cap_result alloc_rpc_cap(Native_capability ep) override { return _real.call(ep); } void free_rpc_cap(Native_capability cap) override { diff --git a/repos/os/src/monitor/monitored_pd.h b/repos/os/src/monitor/monitored_pd.h index a5796b9f3e..d2249e81f2 100644 --- a/repos/os/src/monitor/monitored_pd.h +++ b/repos/os/src/monitor/monitored_pd.h @@ -44,29 +44,39 @@ struct Monitor::Monitored_pd_session : Monitored_rpc_object ** Pd_session interface ** **************************/ - void ref_account(Capability pd_cap) override - { - _with_pd_arg(pd_cap, - [&] (Monitored_pd_session &pd) { _real.call(pd._real); }, - [&] { _real.call(pd_cap); }); - } - - void transfer_quota(Capability pd_cap, Cap_quota amount) override + Ref_account_result ref_account(Capability pd_cap) override { + Ref_account_result result = Ref_account_result::INVALID_SESSION; _with_pd_arg(pd_cap, [&] (Monitored_pd_session &pd) { - _real.call(pd._real, amount); }, + result = _real.call(pd._real); }, [&] { - _real.call(pd_cap, amount); }); + result = _real.call(pd_cap); }); + return result; } - void transfer_quota(Pd_session_capability pd_cap, Ram_quota amount) override + Transfer_cap_quota_result transfer_quota(Capability pd_cap, + Cap_quota amount) override { + Transfer_cap_quota_result result = Transfer_cap_quota_result::INVALID_SESSION; _with_pd_arg(pd_cap, [&] (Monitored_pd_session &pd) { - _real.call(pd._real, amount); }, + result = _real.call(pd._real, amount); }, [&] { - _real.call(pd_cap, amount); }); + result = _real.call(pd_cap, amount); }); + return result; + } + + Transfer_ram_quota_result transfer_quota(Pd_session_capability pd_cap, + Ram_quota amount) override + { + Transfer_ram_quota_result result = Transfer_ram_quota_result::INVALID_SESSION; + _with_pd_arg(pd_cap, + [&] (Monitored_pd_session &pd) { + result = _real.call(pd._real, amount); }, + [&] { + result = _real.call(pd_cap, amount); }); + return result; } }; diff --git a/repos/os/src/monitor/pd_intrinsics.h b/repos/os/src/monitor/pd_intrinsics.h index e75d516e6f..d9dc618a74 100644 --- a/repos/os/src/monitor/pd_intrinsics.h +++ b/repos/os/src/monitor/pd_intrinsics.h @@ -35,7 +35,7 @@ struct Monitor::Pd_intrinsics : Sandbox::Pd_intrinsics { using Monitored_pd_session::Monitored_pd_session; - using Sig_src_cap = Signal_source_capability; + using Sig_src_cap = Capability; using Sig_ctx_cap = Signal_context_capability; using Ram_ds_cap = Ram_dataspace_capability; using Mng_sys_state = Managing_system_state; @@ -43,13 +43,13 @@ struct Monitor::Pd_intrinsics : Sandbox::Pd_intrinsics void assign_parent(Capability) override { never_called(__func__); }; bool assign_pci(addr_t, uint16_t) override { never_called(__func__); }; - void map(addr_t, addr_t) override { never_called(__func__); }; - Sig_src_cap alloc_signal_source() override { never_called(__func__); }; + Map_result map(Virt_range) override { never_called(__func__); }; + Signal_source_result signal_source() override { never_called(__func__); }; void free_signal_source(Sig_src_cap) override { never_called(__func__); }; Alloc_context_result alloc_context(Sig_src_cap, Imprint) override { never_called(__func__); }; void free_context(Sig_ctx_cap) override { never_called(__func__); }; void submit(Sig_ctx_cap, unsigned) override { never_called(__func__); }; - Native_capability alloc_rpc_cap(Native_capability) override { never_called(__func__); }; + Alloc_rpc_cap_result alloc_rpc_cap(Native_capability) override { never_called(__func__); }; void free_rpc_cap(Native_capability) override { never_called(__func__); }; Capability address_space() override { never_called(__func__); }; Capability stack_area() override { never_called(__func__); };