diff --git a/repos/base/run/platform_drv.inc b/repos/base/run/platform_drv.inc index 679d2b9ff8..be944b2928 100644 --- a/repos/base/run/platform_drv.inc +++ b/repos/base/run/platform_drv.inc @@ -245,6 +245,9 @@ proc platform_drv_config {} { append_if [have_board pc] drv_config { } + append_if [expr [have_spec x86]] drv_config { + } + append_if [expr [have_board rpi] || [have_board pc]] drv_config { } diff --git a/repos/os/src/drivers/platform/spec/x86/main.cc b/repos/os/src/drivers/platform/spec/x86/main.cc index a5da1ca1f3..85a33f8509 100644 --- a/repos/os/src/drivers/platform/spec/x86/main.cc +++ b/repos/os/src/drivers/platform/spec/x86/main.cc @@ -42,8 +42,12 @@ struct Platform::Main Genode::Constructible system_state { }; Genode::Constructible acpi_ready { }; - Genode::Signal_handler _acpi_report; - Genode::Signal_handler _system_report; + Signal_handler
_acpi_report { _env.ep(), *this, + &Main::acpi_update }; + Signal_handler
_system_report { _env.ep(), *this, + &Main::system_update }; + Signal_handler
_config_handler { _env.ep(), *this, + &Main::config_update }; Genode::Capability > root_cap { }; @@ -52,14 +56,22 @@ struct Platform::Main void acpi_update() { - acpi_rom->update(); + if (!root.constructed()) { + acpi_rom->update(); - if (!acpi_rom->valid() || root.constructed()) + if (!acpi_rom->valid()) + return; + + root.construct(_env, sliced_heap, _config, + acpi_rom->local_addr(), _acpi_platform); + } + + if (root_cap.valid()) return; - const char * report_addr = acpi_rom->local_addr(); - - root.construct(_env, sliced_heap, _config, report_addr, _acpi_platform); + /* don't announce service if no policy entry is available */ + if (!root->config_with_policy()) + return; root_cap = _env.ep().manage(*root); @@ -92,6 +104,23 @@ struct Platform::Main } } + void config_update() + { + _config.update(); + + if (!_config.valid()) + return; + + if (!root_cap.valid()) + acpi_update(); + + + if (root.constructed()) { + root->generate_pci_report(); + root->config_update(); + } + } + static bool acpi_platform(Genode::Env & env) { using Name = String<32>; @@ -110,13 +139,12 @@ struct Platform::Main Main(Genode::Env &env) : _env(env), - _acpi_report(_env.ep(), *this, &Main::acpi_update), - _system_report(_env.ep(), *this, &Main::system_update), _acpi_platform(acpi_platform(env)) { - const Genode::Xml_node config = _config.xml(); + _config.sigh(_config_handler); - _acpi_ready = config.attribute_value("acpi_ready", false); + if (_config.valid()) + _acpi_ready = _config.xml().attribute_value("acpi_ready", false); if (_acpi_ready) { acpi_ready.construct(env, "acpi_ready"); diff --git a/repos/os/src/drivers/platform/spec/x86/nonpci_devices.cc b/repos/os/src/drivers/platform/spec/x86/nonpci_devices.cc index 765c1a9f61..16cd8493be 100644 --- a/repos/os/src/drivers/platform/spec/x86/nonpci_devices.cc +++ b/repos/os/src/drivers/platform/spec/x86/nonpci_devices.cc @@ -86,6 +86,8 @@ class Nonpci::Ps2 : public Platform::Device_component { return Genode::Io_mem_session_capability(); } + + virtual String<5> name() const override { return "PS2"; } }; @@ -123,6 +125,8 @@ class Nonpci::Pit : public Platform::Device_component return Genode::Io_port_session_capability(); } + + virtual String<5> name() const override { return "PIT"; } }; diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device_component.h b/repos/os/src/drivers/platform/spec/x86/pci_device_component.h index a5dbeae2ea..925ce0c324 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_device_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_device_component.h @@ -547,6 +547,17 @@ class Platform::Device_component : public Genode::Rpc_object, Device_config device_config() const { return _device_config; } Genode::addr_t config_space() const { return _config_space; } + virtual String<5> name() const { return "PCI"; } + + template + void for_each_device(FUNC const &fn) const + { + fn(*this); + + for (auto *dev = this; dev; dev = dev->next()) { + fn(*dev); } + } + /************************** ** PCI-device interface ** **************************/ diff --git a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h index 1ccfc603ee..ecca81032b 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h @@ -214,13 +214,13 @@ class Platform::Session_component : public Genode::Rpc_object _env.pd(), _ram_guard, _cap_guard }; Genode::Heap _md_alloc; Genode::Session_label const _label; - Genode::Session_policy const _policy { _label, _config.xml() }; Genode::List _device_list { }; Platform::Pci_buses &_pci_bus; Genode::Heap &_global_heap; Pci::Config::Delayer &_delayer; Device_bars_pool &_devices_bars; bool _iommu; + bool _msi_usage { true }; /** * Registry of RAM dataspaces allocated by the session @@ -325,8 +325,10 @@ class Platform::Session_component : public Genode::Rpc_object { using namespace Genode; + Session_policy const policy { _label, _config.xml() }; + try { - _policy.for_each_sub_node("device", [&] (Xml_node dev) { + policy.for_each_sub_node("device", [&] (Xml_node dev) { /* enforce restriction based on name name */ if (dev.attribute_value("name", Genode::String<10>()) == name) @@ -373,7 +375,9 @@ class Platform::Session_component : public Genode::Rpc_object using namespace Genode; try { - _policy.for_each_sub_node("pci", [&] (Xml_node node) { + Session_policy const policy { _label, _config.xml() }; + + policy.for_each_sub_node("pci", [&] (Xml_node node) { if (_bdf_exactly_specified(node)) { if (_bdf_matches(node, bdf)) @@ -488,8 +492,18 @@ class Platform::Session_component : public Genode::Rpc_object /* subtract the RPC session and session dataspace capabilities */ _cap_guard.withdraw(Genode::Cap_quota{2}); + check_for_policy(); + } + + void check_for_policy() + { + Session_policy const policy { _label, _config.xml() }; + + typedef Genode::String<10> Mode; + _msi_usage = policy.attribute_value("irq_mode", Mode()) != "nomsi"; + /* check policy for non-pci devices */ - _policy.for_each_sub_node("device", [&] (Genode::Xml_node device_node) { + policy.for_each_sub_node("device", [&] (Genode::Xml_node device_node) { if (!device_node.has_attribute("name")) { Genode::error("'", _label, "' - device node " @@ -509,7 +523,7 @@ class Platform::Session_component : public Genode::Rpc_object }); /* pci devices */ - _policy.for_each_sub_node("pci", [&] (Genode::Xml_node node) { + policy.for_each_sub_node("pci", [&] (Genode::Xml_node node) { enum { INVALID_CLASS = 0x1000000U }; @@ -571,6 +585,40 @@ class Platform::Session_component : public Genode::Rpc_object }); } + bool policy_valid() + { + try { + /* check that policy is available */ + check_for_policy(); + } catch (...) { + return false; + } + + /* check that device entries in policy are still permitted */ + if (!_device_list.first()) + return true; + + bool result = true; + + _device_list.first()->for_each_device([&](auto const &dev) { + + /* Non PCI devices */ + if (!dev.device_config().valid()) { + if (!permit_device(dev.name().string())) + result = false; + + return; + } + + /* PCI devices */ + if (!permit_device(dev.device_config().bdf(), + dev.device_config().class_code())) + result = false; + }); + + return result; + } + /** * Destructor */ @@ -610,11 +658,7 @@ class Platform::Session_component : public Genode::Rpc_object /** * Check whether msi usage was explicitly switched off */ - bool msi_usage() - { - typedef Genode::String<10> Mode; - return _policy.attribute_value("irq_mode", Mode()) != "nomsi"; - } + bool msi_usage() const { return _msi_usage; } /*************************** @@ -821,7 +865,8 @@ class Platform::Root : public Genode::Root_component Device_bars_pool _devices_bars { }; Genode::Constructible _buses { }; - bool _iommu { false }; + bool _iommu { false }; + bool _pci_reported { false }; struct Timer_delayer : Pci::Config::Delayer, Timer::Connection { @@ -830,6 +875,8 @@ class Platform::Root : public Genode::Root_component void usleep(uint64_t us) override { Timer::Connection::usleep(us); } } _delayer { _env }; + Genode::Registry > _sessions { }; + void _parse_report_rom(Genode::Env &env, const char * acpi_rom, bool acpi_platform) { @@ -1014,10 +1061,14 @@ class Platform::Root : public Genode::Root_component Session_component *_create_session(const char *args) override { try { - return new (md_alloc()) - Session_component(_env, _config, *_pci_confspace, *_buses, - _heap, _delayer, _devices_bars, args, - _iommu); + return new (md_alloc()) + Genode::Registered(_sessions, _env, + _config, + *_pci_confspace, + *_buses, _heap, + _delayer, + _devices_bars, args, + _iommu); } catch (Genode::Session_policy::No_policy_defined) { Genode::error("Invalid session request, no matching policy for ", @@ -1065,8 +1116,16 @@ class Platform::Root : public Genode::Root_component _construct_buses(); - if (config.xml().has_sub_node("report") - && config.xml().sub_node("report").attribute_value("pci", true)) { + generate_pci_report(); + } + + void generate_pci_report() + { + if (!_pci_reported && _config.valid() && + _config.xml().has_sub_node("report") && + _config.xml().sub_node("report").attribute_value("pci", false)) { + + _pci_reported = true; _pci_reporter.construct(_env, "pci", "pci"); @@ -1091,7 +1150,9 @@ class Platform::Root : public Genode::Root_component using Genode::Hex; xml.node("device", [&] () { - xml.attribute("bdf" , String<8>(Hex(bus, Hex::Prefix::OMIT_PREFIX), ":", Hex(device, Hex::Prefix::OMIT_PREFIX), ".", function)); + xml.attribute("bus" , String<5>(Hex(bus))); + xml.attribute("device" , String<5>(Hex(device))); + xml.attribute("function" , String<5>(Hex(function))); xml.attribute("vendor_id" , String<8>(Hex(config.vendor_id()))); xml.attribute("device_id" , String<8>(Hex(config.device_id()))); xml.attribute("class_code", String<12>(Hex(config.class_code()))); @@ -1118,4 +1179,15 @@ class Platform::Root : public Genode::Root_component }); } } + + bool config_with_policy() const { + return _config.valid() && _config.xml().has_sub_node("policy"); } + + void config_update() + { + _sessions.for_each([&](auto &session) { + if (!session.policy_valid()) + destroy(session); + }); + } };