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);
+ });
+ }
};