genode/repos/ports/src/app/gdb_monitor/app_child.h

359 lines
11 KiB
C
Raw Normal View History

2011-12-22 16:19:25 +01:00
/*
* \brief Application child
* \author Christian Prochaska
* \date 2009-10-05
*/
/*
* Copyright (C) 2009-2017 Genode Labs GmbH
2011-12-22 16:19:25 +01:00
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
2011-12-22 16:19:25 +01:00
*/
#ifndef _APP_CHILD_H_
#define _APP_CHILD_H_
/* Genode includes */
2011-12-22 16:19:25 +01:00
#include <base/child.h>
#include <base/service.h>
#include <init/child_policy.h>
#include <os/session_requester.h>
2011-12-22 16:19:25 +01:00
#include <util/arg_string.h>
/* init private includes */
#include <init/server.h>
/* GDB monitor includes */
#include "genode_child_resources.h"
#include "cpu_session_component.h"
#include "pd_session_component.h"
2011-12-22 16:19:25 +01:00
#include "rom.h"
#include "child_config.h"
2011-12-22 16:19:25 +01:00
namespace Gdb_monitor {
using namespace Genode;
2011-12-22 16:19:25 +01:00
class App_child;
}
2011-12-22 16:19:25 +01:00
class Gdb_monitor::App_child : public Child_policy,
public Async_service::Wakeup,
public Init::Report_update_trigger,
public Init::Routed_service::Pd_accessor,
public Init::Routed_service::Ram_accessor
{
private:
2011-12-22 16:19:25 +01:00
typedef Registered<Genode::Parent_service> Parent_service;
typedef Registry<Parent_service> Parent_services;
typedef Registry<Init::Routed_service> Child_services;
2011-12-22 16:19:25 +01:00
/**
* gdbserver blocks in 'select()', so a separate entrypoint is used.
*/
struct Local_env : Genode::Env
{
Genode::Env &genode_env;
Genode::Entrypoint local_ep {
genode_env, 4*1024*sizeof(addr_t), "target_ep", Affinity::Location() };
Local_env(Env &genode_env) : genode_env(genode_env) { }
2011-12-22 16:19:25 +01:00
Parent &parent() override { return genode_env.parent(); }
Cpu_session &cpu() override { return genode_env.cpu(); }
Region_map &rm() override { return genode_env.rm(); }
Pd_session &pd() override { return genode_env.pd(); }
Entrypoint &ep() override { return local_ep; }
Cpu_session_capability cpu_session_cap() override { return genode_env.cpu_session_cap(); }
Pd_session_capability pd_session_cap() override { return genode_env.pd_session_cap(); }
Id_space<Parent::Client> &id_space() override { return genode_env.id_space(); }
Pd_session_capability ram_session_cap() { return pd_session_cap(); }
Pd_session &ram() { return pd(); }
2011-12-22 16:19:25 +01:00
Session_capability session(Parent::Service_name const &service_name,
Parent::Client::Id id,
Parent::Session_args const &session_args,
Affinity const &affinity) override
{ return genode_env.session(service_name, id, session_args, affinity); }
void upgrade(Parent::Client::Id id, Parent::Upgrade_args const &args) override
{ return genode_env.upgrade(id, args); }
void close(Parent::Client::Id id) override { return genode_env.close(id); }
void exec_static_constructors() override { }
void reinit(Native_capability::Raw raw) override {
genode_env.reinit(raw);
}
void reinit_main_thread(Capability<Region_map> &stack_area_rm) override {
genode_env.reinit_main_thread(stack_area_rm);
}
};
Local_env _env;
Allocator &_alloc;
Capability quota accounting and trading This patch mirrors the accounting and trading scheme that Genode employs for physical memory to the accounting of capability allocations. Capability quotas must now be explicitly assigned to subsystems by specifying a 'caps=<amount>' attribute to init's start nodes. Analogously to RAM quotas, cap quotas can be traded between clients and servers as part of the session protocol. The capability budget of each component is maintained by the component's corresponding PD session at core. At the current stage, the accounting is applied to RPC capabilities, signal-context capabilities, and dataspace capabilities. Capabilities that are dynamically allocated via core's CPU and TRACE service are not yet covered. Also, the capabilities allocated by resource multiplexers outside of core (like nitpicker) must be accounted by the respective servers, which is not covered yet. If a component runs out of capabilities, core's PD service prints a warning to the log. To observe the consumption of capabilities per component in detail, the PD service is equipped with a diagnostic mode, which can be enabled via the 'diag' attribute in the target node of init's routing rules. E.g., the following route enables the diagnostic mode for the PD session of the "timer" component: <default-route> <service name="PD" unscoped_label="timer"> <parent diag="yes"/> </service> ... </default-route> For subsystems based on a sub-init instance, init can be configured to report the capability-quota information of its subsystems by adding the attribute 'child_caps="yes"' to init's '<report>' config node. Init's own capability quota can be reported by adding the attribute 'init_caps="yes"'. Fixes #2398
2017-05-08 21:35:43 +02:00
Pd_session_capability _ref_pd_cap { _env.pd_session_cap() };
Pd_session &_ref_pd { _env.pd() };
const char *_unique_name;
2011-12-22 16:19:25 +01:00
Dataspace_capability _elf_ds;
2011-12-22 16:19:25 +01:00
Region_map &_rm;
2011-12-22 16:19:25 +01:00
Ram_quota _ram_quota;
Capability quota accounting and trading This patch mirrors the accounting and trading scheme that Genode employs for physical memory to the accounting of capability allocations. Capability quotas must now be explicitly assigned to subsystems by specifying a 'caps=<amount>' attribute to init's start nodes. Analogously to RAM quotas, cap quotas can be traded between clients and servers as part of the session protocol. The capability budget of each component is maintained by the component's corresponding PD session at core. At the current stage, the accounting is applied to RPC capabilities, signal-context capabilities, and dataspace capabilities. Capabilities that are dynamically allocated via core's CPU and TRACE service are not yet covered. Also, the capabilities allocated by resource multiplexers outside of core (like nitpicker) must be accounted by the respective servers, which is not covered yet. If a component runs out of capabilities, core's PD service prints a warning to the log. To observe the consumption of capabilities per component in detail, the PD service is equipped with a diagnostic mode, which can be enabled via the 'diag' attribute in the target node of init's routing rules. E.g., the following route enables the diagnostic mode for the PD session of the "timer" component: <default-route> <service name="PD" unscoped_label="timer"> <parent diag="yes"/> </service> ... </default-route> For subsystems based on a sub-init instance, init can be configured to report the capability-quota information of its subsystems by adding the attribute 'child_caps="yes"' to init's '<report>' config node. Init's own capability quota can be reported by adding the attribute 'init_caps="yes"'. Fixes #2398
2017-05-08 21:35:43 +02:00
Cap_quota _cap_quota;
Parent_services _parent_services;
Child_services _child_services;
Init::Child_config _child_config;
2011-12-22 16:19:25 +01:00
Init::Child_policy_provide_rom_file _config_policy;
2011-12-22 16:19:25 +01:00
Genode_child_resources _genode_child_resources;
2011-12-22 16:19:25 +01:00
Signal_handler<App_child> _unresolved_page_fault_handler;
2011-12-22 16:19:25 +01:00
Dataspace_pool _managed_ds_map;
2011-12-22 16:19:25 +01:00
Pd_session_component _pd { _env.ep().rpc_ep(),
_env,
_alloc,
_unique_name,
_managed_ds_map };
Pd_service::Single_session_factory _pd_factory { _pd };
Pd_service _pd_service { _pd_factory };
2011-12-22 16:19:25 +01:00
Local_cpu_factory _cpu_factory;
Cpu_service _cpu_service { _cpu_factory };
2011-12-22 16:19:25 +01:00
Local_rom_factory _rom_factory;
Rom_service _rom_service { _rom_factory };
2011-12-22 16:19:25 +01:00
Genode::Session_requester _session_requester { _env.ep().rpc_ep(),
_env.ram(),
_env.rm() };
Init::Server _server { _env, _alloc, _child_services, *this };
Child *_child;
2011-12-22 16:19:25 +01:00
void _handle_unresolved_page_fault()
{
_genode_child_resources.cpu_session_component().handle_unresolved_page_fault();
}
template <typename T>
static Service *_find_service(Registry<T> &services,
Service::Name const &name)
{
Service *service = nullptr;
services.for_each([&] (T &s) {
if (!service && (s.name() == name))
service = &s; });
return service;
}
/**
* Child_service::Wakeup callback
*/
void wakeup_async_service() override
{
_session_requester.trigger_update();
}
/**
* Init::Report_update_trigger callbacks
*/
void trigger_report_update() override { }
void trigger_immediate_report_update() override { }
/**
* Init::Routed_service::Pd_accessor interface
*/
Pd_session &pd() override { return _child->pd(); }
Pd_session_capability pd_cap() const override { return _child->pd_session_cap(); }
/**
* Init::Routed_service::Ram_accessor interface
*/
Pd_session &ram() override { return _child->pd(); }
Pd_session_capability ram_cap() const override { return _child->pd_session_cap(); }
Service &_matching_service(Service::Name const &service_name,
Session_label const &label)
{
Service *service = nullptr;
/* check for config file request */
if ((service = _config_policy.resolve_session_request_with_label(service_name, label)))
return *service;
/* check for "session_requests" ROM request */
if ((service_name == Genode::Rom_session::service_name()) &&
(label.last_element() == Genode::Session_requester::rom_name()))
return _session_requester.service();
if (service_name == "CPU")
return _cpu_service;
if (service_name == "PD")
return _pd_service;
if (service_name == "ROM")
return _rom_service;
service = _find_service(_parent_services, service_name);
if (!service)
service = new (_alloc) Parent_service(_parent_services, _env, service_name);
if (!service)
throw Service_denied();
return *service;
}
public:
/**
* Constructor
*/
App_child(Env &env,
Allocator &alloc,
char const *unique_name,
Ram_quota ram_quota,
Cap_quota cap_quota,
Entrypoint &signal_ep,
Xml_node target_node,
int const new_thread_pipe_write_end,
int const breakpoint_len,
unsigned char const *breakpoint_data)
:
_env(env),
_alloc(alloc),
_unique_name(unique_name),
_rm(_env.rm()),
Capability quota accounting and trading This patch mirrors the accounting and trading scheme that Genode employs for physical memory to the accounting of capability allocations. Capability quotas must now be explicitly assigned to subsystems by specifying a 'caps=<amount>' attribute to init's start nodes. Analogously to RAM quotas, cap quotas can be traded between clients and servers as part of the session protocol. The capability budget of each component is maintained by the component's corresponding PD session at core. At the current stage, the accounting is applied to RPC capabilities, signal-context capabilities, and dataspace capabilities. Capabilities that are dynamically allocated via core's CPU and TRACE service are not yet covered. Also, the capabilities allocated by resource multiplexers outside of core (like nitpicker) must be accounted by the respective servers, which is not covered yet. If a component runs out of capabilities, core's PD service prints a warning to the log. To observe the consumption of capabilities per component in detail, the PD service is equipped with a diagnostic mode, which can be enabled via the 'diag' attribute in the target node of init's routing rules. E.g., the following route enables the diagnostic mode for the PD session of the "timer" component: <default-route> <service name="PD" unscoped_label="timer"> <parent diag="yes"/> </service> ... </default-route> For subsystems based on a sub-init instance, init can be configured to report the capability-quota information of its subsystems by adding the attribute 'child_caps="yes"' to init's '<report>' config node. Init's own capability quota can be reported by adding the attribute 'init_caps="yes"'. Fixes #2398
2017-05-08 21:35:43 +02:00
_ram_quota(ram_quota), _cap_quota(cap_quota),
_child_config(_env.ram(), _rm, target_node),
_config_policy("config", _child_config.dataspace(), &_env.ep().rpc_ep()),
_unresolved_page_fault_handler(signal_ep, *this,
&App_child::_handle_unresolved_page_fault),
_cpu_factory(_env, _env.ep().rpc_ep(), _alloc, _pd.core_pd_cap(),
signal_ep, new_thread_pipe_write_end,
breakpoint_len, breakpoint_data,
&_genode_child_resources),
_rom_factory(_env, _env.ep().rpc_ep(), _alloc)
{
_genode_child_resources.region_map_component(&_pd.region_map());
_pd.region_map().fault_handler(_unresolved_page_fault_handler);
}
~App_child()
{
_child_services.for_each([&] (Init::Routed_service &service) {
destroy(_alloc, &service);
});
destroy(_alloc, _child);
}
Genode_child_resources *genode_child_resources()
{
return &_genode_child_resources;
}
void start()
{
_child = new (_alloc) Child(_rm, _env.ep().rpc_ep(), *this);
}
/****************************
** Child-policy interface **
****************************/
Name name() const override { return _unique_name; }
Capability quota accounting and trading This patch mirrors the accounting and trading scheme that Genode employs for physical memory to the accounting of capability allocations. Capability quotas must now be explicitly assigned to subsystems by specifying a 'caps=<amount>' attribute to init's start nodes. Analogously to RAM quotas, cap quotas can be traded between clients and servers as part of the session protocol. The capability budget of each component is maintained by the component's corresponding PD session at core. At the current stage, the accounting is applied to RPC capabilities, signal-context capabilities, and dataspace capabilities. Capabilities that are dynamically allocated via core's CPU and TRACE service are not yet covered. Also, the capabilities allocated by resource multiplexers outside of core (like nitpicker) must be accounted by the respective servers, which is not covered yet. If a component runs out of capabilities, core's PD service prints a warning to the log. To observe the consumption of capabilities per component in detail, the PD service is equipped with a diagnostic mode, which can be enabled via the 'diag' attribute in the target node of init's routing rules. E.g., the following route enables the diagnostic mode for the PD session of the "timer" component: <default-route> <service name="PD" unscoped_label="timer"> <parent diag="yes"/> </service> ... </default-route> For subsystems based on a sub-init instance, init can be configured to report the capability-quota information of its subsystems by adding the attribute 'child_caps="yes"' to init's '<report>' config node. Init's own capability quota can be reported by adding the attribute 'init_caps="yes"'. Fixes #2398
2017-05-08 21:35:43 +02:00
Pd_session &ref_pd() override { return _ref_pd; }
Pd_session_capability ref_pd_cap() const override { return _ref_pd_cap; }
Id_space<Parent::Server> &server_id_space() override
{
return _session_requester.id_space();
}
Capability quota accounting and trading This patch mirrors the accounting and trading scheme that Genode employs for physical memory to the accounting of capability allocations. Capability quotas must now be explicitly assigned to subsystems by specifying a 'caps=<amount>' attribute to init's start nodes. Analogously to RAM quotas, cap quotas can be traded between clients and servers as part of the session protocol. The capability budget of each component is maintained by the component's corresponding PD session at core. At the current stage, the accounting is applied to RPC capabilities, signal-context capabilities, and dataspace capabilities. Capabilities that are dynamically allocated via core's CPU and TRACE service are not yet covered. Also, the capabilities allocated by resource multiplexers outside of core (like nitpicker) must be accounted by the respective servers, which is not covered yet. If a component runs out of capabilities, core's PD service prints a warning to the log. To observe the consumption of capabilities per component in detail, the PD service is equipped with a diagnostic mode, which can be enabled via the 'diag' attribute in the target node of init's routing rules. E.g., the following route enables the diagnostic mode for the PD session of the "timer" component: <default-route> <service name="PD" unscoped_label="timer"> <parent diag="yes"/> </service> ... </default-route> For subsystems based on a sub-init instance, init can be configured to report the capability-quota information of its subsystems by adding the attribute 'child_caps="yes"' to init's '<report>' config node. Init's own capability quota can be reported by adding the attribute 'init_caps="yes"'. Fixes #2398
2017-05-08 21:35:43 +02:00
void init(Pd_session &session,
Pd_session_capability cap) override
{
session.ref_account(_ref_pd_cap);
_env.ep().rpc_ep().apply(cap, [&] (Pd_session_component *pd) {
if (pd) {
_ref_pd.transfer_quota(pd->core_pd_cap(), _cap_quota);
_ref_pd.transfer_quota(pd->core_pd_cap(), _ram_quota);
}
});
Capability quota accounting and trading This patch mirrors the accounting and trading scheme that Genode employs for physical memory to the accounting of capability allocations. Capability quotas must now be explicitly assigned to subsystems by specifying a 'caps=<amount>' attribute to init's start nodes. Analogously to RAM quotas, cap quotas can be traded between clients and servers as part of the session protocol. The capability budget of each component is maintained by the component's corresponding PD session at core. At the current stage, the accounting is applied to RPC capabilities, signal-context capabilities, and dataspace capabilities. Capabilities that are dynamically allocated via core's CPU and TRACE service are not yet covered. Also, the capabilities allocated by resource multiplexers outside of core (like nitpicker) must be accounted by the respective servers, which is not covered yet. If a component runs out of capabilities, core's PD service prints a warning to the log. To observe the consumption of capabilities per component in detail, the PD service is equipped with a diagnostic mode, which can be enabled via the 'diag' attribute in the target node of init's routing rules. E.g., the following route enables the diagnostic mode for the PD session of the "timer" component: <default-route> <service name="PD" unscoped_label="timer"> <parent diag="yes"/> </service> ... </default-route> For subsystems based on a sub-init instance, init can be configured to report the capability-quota information of its subsystems by adding the attribute 'child_caps="yes"' to init's '<report>' config node. Init's own capability quota can be reported by adding the attribute 'init_caps="yes"'. Fixes #2398
2017-05-08 21:35:43 +02:00
}
Route resolve_session_request(Service::Name const &service_name,
Session_label const &label) override
{
return Route { .service = _matching_service(service_name, label),
.label = label,
.diag = Session::Diag() };
}
void announce_service(Service::Name const &service_name) override
{
if (_find_service(_child_services, service_name)) {
Genode::warning(name(), ": service ", service_name, " is already registered");
return;
}
new (_alloc) Init::Routed_service(_child_services,
"target",
*this, *this,
_session_requester.id_space(),
_child->session_factory(),
service_name,
*this);
char server_config[4096];
try {
Xml_generator xml(server_config, sizeof(server_config),
"config", [&] () {
_child_services.for_each([&] (Service &service) {
xml.node("service", [&] () {
xml.attribute("name", service_name);
xml.node("default-policy", [&] () {
xml.node("child", [&] () {
xml.attribute("name", "target");
});
});
});
});
});
_server.apply_config(Xml_node(server_config));
} catch(Xml_generator::Buffer_exceeded &) {
error("XML buffer for server configuration exceeded");
}
_env.parent().announce(service_name.string());
}
};
2011-12-22 16:19:25 +01:00
#endif /* _APP_CHILD_H_ */