/* * \brief Core main program * \author Norman Feske * \date 2006-07-12 */ /* * Copyright (C) 2006-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. */ /* Genode includes */ #include #include #include #include #include #include #include #include #include /* base-internal includes */ #include /* core includes */ #include #include #include #include #include #include #include #include #include #include #include #include using namespace Genode; /*************************************** ** Core environment/platform support ** ***************************************/ Core_env * Genode::core_env() { /* * Make sure to initialize the platform before constructing the core * environment. */ platform(); /* * By placing the environment as static object here, we ensure that its * constructor gets called when this function is used the first time. */ static Core_env _env; return &_env; } Env_deprecated * Genode::env_deprecated() { return core_env(); } Platform *Genode::platform_specific() { static Platform _platform; return &_platform; } Platform_generic *Genode::platform() { return platform_specific(); } /************************* ** Core parent support ** *************************/ Session_capability Core_parent::session(Parent::Client::Id id, Parent::Service_name const &name, Parent::Session_args const &args, Affinity const &affinity) { Session_capability cap; _services.for_each([&] (Service &service) { if ((service.name() != name.string()) || cap.valid()) return; Session_state &session = *new (_alloc) Session_state(service, _id_space, id, label_from_args(args.string()), args.string(), affinity); service.initiate_request(session); cap = session.cap; }); if (!cap.valid()) error("unexpected core-parent ", name.string(), " session request"); return cap; } /**************** ** Core child ** ****************/ class Core_child : public Child_policy { private: /* * Entry point used for serving the parent interface */ Rpc_entrypoint _entrypoint; enum { STACK_SIZE = 4 * 1024 * sizeof(Genode::addr_t)}; Registry &_services; Capability _core_pd_cap; Pd_session &_core_pd; Capability _core_ram_cap; Ram_session &_core_ram; Capability _core_cpu_cap; Cpu_session &_core_cpu; Cap_quota const _cap_quota; Ram_quota const _ram_quota; Child _child; public: /** * Constructor */ Core_child(Registry &services, Pd_session &core_pd, Capability core_pd_cap, Ram_session &core_ram, Capability core_ram_cap, Cpu_session &core_cpu, Capability core_cpu_cap, Cap_quota cap_quota, Ram_quota ram_quota) : _entrypoint(nullptr, STACK_SIZE, "init_child", false), _services(services), _core_pd_cap (core_pd_cap), _core_pd (core_pd), _core_ram_cap(core_ram_cap), _core_ram(core_ram), _core_cpu_cap(core_cpu_cap), _core_cpu(core_cpu), _cap_quota(Child::effective_quota(cap_quota)), _ram_quota(Child::effective_quota(ram_quota)), _child(*env_deprecated()->rm_session(), _entrypoint, *this) { _entrypoint.activate(); } /**************************** ** Child-policy interface ** ****************************/ Name name() const { return "init"; } Service &resolve_session_request(Service::Name const &name, Session_state::Args const &args) override { Service *service = nullptr; _services.for_each([&] (Service &s) { if (!service && s.name() == name) service = &s; }); if (!service) throw Parent::Service_denied(); return *service; } void init(Pd_session &session, Capability cap) override { session.ref_account(_core_pd_cap); _core_pd.transfer_quota(cap, _cap_quota); } void init(Ram_session &session, Capability cap) override { session.ref_account(_core_ram_cap); _core_ram.transfer_quota(cap, _ram_quota); } void init(Cpu_session &session, Capability cap) override { session.ref_account(_core_cpu_cap); _core_cpu.transfer_quota(cap, Cpu_session::quota_lim_upscale(100, 100)); } Pd_session &ref_pd() { return _core_pd; } Pd_session_capability ref_pd_cap() const { return _core_pd_cap; } Ram_session &ref_ram() { return _core_ram; } Ram_session_capability ref_ram_cap() const { return _core_ram_cap; } size_t session_alloc_batch_size() const override { return 128; } }; /**************** ** Signal API ** ****************/ /* * In contrast to the 'Platform_env' used by non-core components, core disables * the signal thread but overriding 'Genode::init_signal_thread' with a dummy. * Within core, the signal thread is not needed as core is never supposed to * receive any signals. Otherwise, the signal thread would be the only * non-entrypoint thread within core, which would be a problem on NOVA where * the creation of regular threads within core is unsupported. */ namespace Genode { void init_signal_thread(Env &) { } } /******************* ** Trace support ** *******************/ Trace::Source_registry &Trace::sources() { static Trace::Source_registry inst; return inst; } /*************** ** Core main ** ***************/ namespace Genode { extern bool inhibit_tracing; extern char const *version_string; } int main() { /** * Disable tracing within core because it is currently not fully implemented. */ inhibit_tracing = true; log("Genode ", Genode::version_string); static Trace::Policy_registry trace_policies; /* * Initialize root interfaces for our services */ Rpc_entrypoint *e = core_env()->entrypoint(); Registry &services = core_env()->services(); static Ram_allocator &core_ram_alloc = *core_env()->ram_session(); static Region_map &local_rm = *core_env()->rm_session(); /* * Allocate session meta data on distinct dataspaces to enable independent * destruction (to enable quota trading) of session component objects. */ static Sliced_heap sliced_heap(core_ram_alloc, local_rm); /* * Factory for creating RPC capabilities within core */ static Rpc_cap_factory rpc_cap_factory(sliced_heap); static Pager_entrypoint pager_ep(rpc_cap_factory); static Ram_root ram_root (*e, *platform()->ram_alloc(), local_rm, sliced_heap); static Rom_root rom_root (e, e, platform()->rom_fs(), &sliced_heap); static Rm_root rm_root (e, &sliced_heap, pager_ep); static Cpu_root cpu_root (e, e, &pager_ep, &sliced_heap, Trace::sources()); static Pd_root pd_root (*e, pager_ep, core_ram_alloc, local_rm, sliced_heap); static Log_root log_root (e, &sliced_heap); static Io_mem_root io_mem_root (e, e, platform()->io_mem_alloc(), platform()->ram_alloc(), &sliced_heap); static Irq_root irq_root (core_env()->pd_session(), platform()->irq_alloc(), &sliced_heap); static Trace::Root trace_root (e, &sliced_heap, Trace::sources(), trace_policies); static Core_service rom_service (services, rom_root); static Core_service ram_service (services, ram_root); static Core_service rm_service (services, rm_root); static Core_service cpu_service (services, cpu_root); static Core_service pd_service (services, pd_root); static Core_service log_service (services, log_root); static Core_service io_mem_service (services, io_mem_root); static Core_service irq_service (services, irq_root); static Core_service trace_service (services, trace_root); /* make platform-specific services known to service pool */ platform_add_local_services(e, &sliced_heap, &services); /* calculate number of capabilities to be assigned to init */ size_t const preservered_cap_quota = 1000; if (platform()->max_caps() < preservered_cap_quota) { error("platform cap limit lower than preservation for core"); return -1; } size_t const avail_cap_quota = platform()->max_caps() - preservered_cap_quota; /* PD session representing core */ static Pd_session_component core_pd(*e, Session::Resources { Ram_quota { 16*1024 }, Cap_quota { avail_cap_quota } }, Session::Label("core"), Session::Diag{false}, core_ram_alloc, local_rm, pager_ep, ""); core_pd.init_cap_account(); /* CPU session representing core */ static Cpu_session_component core_cpu(e, e, &pager_ep, &sliced_heap, Trace::sources(), "label=\"core\"", Affinity(), Cpu_session::QUOTA_LIMIT); Cpu_session_capability core_cpu_cap = core_env()->entrypoint()->manage(&core_cpu); /* calculate RAM to be assigned to init */ size_t const platform_ram_limit = platform()->ram_alloc()->avail(); size_t const preserved_ram_quota = 224*1024; if (platform_ram_limit < preserved_ram_quota) { error("platform RAM limit lower than preservation for core"); return -1; } size_t const avail_ram_quota = platform_ram_limit - preserved_ram_quota; log("", avail_ram_quota / (1024*1024), " MiB RAM and ", avail_cap_quota, " caps " "assigned to init"); static Reconstructible init(services, core_pd, core_pd.cap(), *env_deprecated()->ram_session(), env_deprecated()->ram_session_cap(), core_cpu, core_cpu_cap, core_pd.cap_quota(), Ram_quota{avail_ram_quota}); platform()->wait_for_exit(); init.destruct(); return 0; }