mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-01 23:20:55 +00:00
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<Signal_source>' has been removed. Issue #5245
145 lines
6.6 KiB
C++
145 lines
6.6 KiB
C++
/*
|
|
* \brief Sandbox::Pd_intrinsics for intercepting the PD access of children
|
|
* \author Norman Feske
|
|
* \date 2023-05-10
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2023 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 _PD_INTRINSICS_H_
|
|
#define _PD_INTRINSICS_H_
|
|
|
|
/* Genode includes */
|
|
#include <pd_session/connection.h>
|
|
|
|
/* local includes */
|
|
#include <monitored_cpu.h>
|
|
|
|
namespace Monitor { struct Pd_intrinsics; }
|
|
|
|
|
|
struct Monitor::Pd_intrinsics : Sandbox::Pd_intrinsics
|
|
{
|
|
Env &_env;
|
|
|
|
/*
|
|
* The sandbox interacts with the 'Monitored_ref_pd' only for quota
|
|
* transfers to the children, in particular during the child creation.
|
|
*/
|
|
struct Monitored_ref_pd : Monitored_pd_session
|
|
{
|
|
using Monitored_pd_session::Monitored_pd_session;
|
|
|
|
using Sig_src_cap = Capability<Signal_source>;
|
|
using Sig_ctx_cap = Signal_context_capability;
|
|
using Ram_ds_cap = Ram_dataspace_capability;
|
|
using Mng_sys_state = Managing_system_state;
|
|
using Control_cap = Capability<System_control>;
|
|
|
|
void assign_parent(Capability<Parent>) override { never_called(__func__); };
|
|
bool assign_pci(addr_t, uint16_t) 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__); };
|
|
Alloc_rpc_cap_result alloc_rpc_cap(Native_capability) override { never_called(__func__); };
|
|
void free_rpc_cap(Native_capability) override { never_called(__func__); };
|
|
Capability<Region_map> address_space() override { never_called(__func__); };
|
|
Capability<Region_map> stack_area() override { never_called(__func__); };
|
|
Capability<Region_map> linker_area() override { never_called(__func__); };
|
|
Cap_quota cap_quota() const override { never_called(__func__); };
|
|
Cap_quota used_caps() const override { never_called(__func__); };
|
|
Alloc_result try_alloc(size_t, Cache) override { never_called(__func__); };
|
|
void free(Ram_ds_cap) override { never_called(__func__); };
|
|
size_t dataspace_size(Ram_ds_cap) const override { never_called(__func__); };
|
|
Ram_quota ram_quota() const override { never_called(__func__); };
|
|
Ram_quota used_ram() const override { never_called(__func__); };
|
|
Capability<Native_pd> native_pd() override { never_called(__func__); };
|
|
Control_cap system_control_cap(Affinity::Location) override { never_called(__func__); };
|
|
addr_t dma_addr(Ram_ds_cap) override { never_called(__func__); };
|
|
Attach_dma_result attach_dma(Dataspace_capability, addr_t) override { never_called(__func__); };
|
|
|
|
} _monitored_ref_pd { _env.ep(), _env.pd_session_cap(), Session::Label { } };
|
|
|
|
struct Monitored_ref_cpu : Monitored_cpu_session
|
|
{
|
|
using Monitored_cpu_session::Monitored_cpu_session;
|
|
|
|
using Sig_ctx_cap = Signal_context_capability;
|
|
|
|
Thread_capability
|
|
create_thread(Capability<Pd_session>, Cpu_session::Name const &,
|
|
Affinity::Location, Weight, addr_t) override { never_called(__func__); }
|
|
void kill_thread(Thread_capability) override { never_called(__func__); }
|
|
void exception_sigh(Sig_ctx_cap) override { never_called(__func__); }
|
|
Affinity::Space affinity_space() const override { never_called(__func__); }
|
|
Dataspace_capability trace_control() override { never_called(__func__); }
|
|
Quota quota() override { never_called(__func__); }
|
|
Capability<Native_cpu> native_cpu() override { never_called(__func__); }
|
|
|
|
} _monitored_ref_cpu { _env.ep(), _env.cpu_session_cap(), Session::Label { } };
|
|
|
|
void with_intrinsics(Capability<Pd_session> pd_cap, Pd_session &pd, Fn const &fn) override
|
|
{
|
|
/*
|
|
* Depending on the presence of the PD session in our local entrypoint,
|
|
* we know whether the child is to be monitored or not.
|
|
*
|
|
* If not monitored, we provide the default PD intrinsics as done by
|
|
* init, using the 'Env' as reference PD session and accessing the
|
|
* child's address space via RPC. For such childen, the monitor
|
|
* functions exactly like init with no indirection.
|
|
*
|
|
* For monitored childen, we provide the '_monitored_ref_pd' and
|
|
* '_monitored_ref_cpu' to get hold of all interactions between the
|
|
* child and its reference PD. Furthermore, the sandbox' interplay with
|
|
* the child's address space is redirected to the locally implemented
|
|
* 'Monitored_region_map'.
|
|
*/
|
|
Inferior_pd::with_inferior_pd(_env.ep(), pd_cap,
|
|
[&] (Inferior_pd &inferior_pd) {
|
|
|
|
Intrinsics intrinsics { .ref_pd = _monitored_ref_pd,
|
|
.ref_pd_cap = _monitored_ref_pd.cap(),
|
|
.ref_cpu = _monitored_ref_cpu,
|
|
.ref_cpu_cap = _monitored_ref_cpu.cap(),
|
|
.address_space = inferior_pd._address_space };
|
|
fn.call(intrinsics);
|
|
},
|
|
[&] /* PD session not intercepted */ {
|
|
|
|
Region_map_client region_map(pd.address_space());
|
|
|
|
Intrinsics intrinsics { .ref_pd = _env.pd(),
|
|
.ref_pd_cap = _env.pd_session_cap(),
|
|
.ref_cpu = _env.cpu(),
|
|
.ref_cpu_cap = _env.cpu_session_cap(),
|
|
.address_space = region_map };
|
|
fn.call(intrinsics);
|
|
}
|
|
);
|
|
}
|
|
|
|
void start_initial_thread(Capability<Cpu_thread> cap, addr_t ip) override
|
|
{
|
|
Monitored_thread::with_thread(_env.ep(), cap,
|
|
[&] (Monitored_thread &monitored_thread) {
|
|
monitored_thread.start(ip, 0);
|
|
},
|
|
[&] /* PD session not intercepted */ {
|
|
Cpu_thread_client(cap).start(ip, 0);
|
|
});
|
|
}
|
|
|
|
Pd_intrinsics(Env &env) : _env(env) { }
|
|
};
|
|
|
|
#endif /* _PD_INTRINSICS_H_ */
|