diff --git a/repos/os/run/platform_drv.run b/repos/os/run/platform_drv.run
index e1c9502297..d4e08442d4 100644
--- a/repos/os/run/platform_drv.run
+++ b/repos/os/run/platform_drv.run
@@ -10,6 +10,7 @@ import_from_depot [depot_user]/src/[base_src] \
[depot_user]/src/fs_report \
[depot_user]/src/fs_rom \
[depot_user]/src/platform_drv \
+ [depot_user]/src/report_rom \
[depot_user]/src/vfs_import \
[depot_user]/src/vfs
@@ -75,12 +76,25 @@ install_config {
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
@@ -105,70 +119,70 @@ append qemu_args "-nographic "
set good_string {
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv] Error: Device 0 not valid!
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
-[init -> test-platform_drv]
+[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
[init -> test-platform_drv]
@@ -177,6 +191,6 @@ set good_string {
[init -> test-platform_drv] Test has ended!
}
-run_genode_until "No matching policy for 'test-platform_drv -> ' anymore, will close the session!.*\n" 100
+run_genode_until "Test has ended!.*\n" 100
grep_output "init -> test-platform_drv"
compare_output_to $good_string
diff --git a/repos/os/src/drivers/platform/README b/repos/os/src/drivers/platform/README
new file mode 100644
index 0000000000..e059d4efbb
--- /dev/null
+++ b/repos/os/src/drivers/platform/README
@@ -0,0 +1,64 @@
+This directory contains the implementation of Genode's platform driver.
+
+Behavior
+--------
+
+Per client a policy must be configured that states which client can
+access certain devices to form a virtual bus per client. The client may
+iterate through the virtual bus using the devices_rom() function of
+the platform_session interface to discover all available devices of the virtual
+bus. When identified a specific device its device capability can be obtained
+via its unique name. Simple device drivers that drive exactly one device do
+not need the devices ROM, but can simply obtain their device capability via
+the acquire_single_device() function of the platform session interface.
+
+With the device capability the resources of the devices can be obtained, e.g.
+io_port, io_mem and irq of the platform_device interface.
+
+Policy usage
+------------
+
+A policy may contain several nodes describing several devices.
+
+!
+!
+! ...
+!
+!
+!
+!
+!
+!
+! ...
+
+The managing_system attribute is evaluated by init. If set to "yes" it
+permits a component, the platform driver, to restrict the allocation of memory to
+specific physical RAM ranges. The platform driver uses this feature to ensure that
+the allocation of DMA capable memory consider several restrictions. For
+example, some drivers, as the UHCI controller, requires a
+physical memory address below 4G. Another example is that on 32bit hosts
+physical to virtual identical mappings of DMA memory for the device_pd
+(required when IOMMU is used) must be below the kernel memory boundary (3G).
+On some systems, e.g., base-hw kernel on certain ARM platforms, it allows the
+platform driver to call system management firmware via kernel syscalls.
+
+The 'info' attribute in a policy node describe, whether the client gets
+permission to access a devices ROM containing detailed information about
+the devices of its virtual bus.
+
+Report facilities
+-----------------
+
+The configuration of the platform driver supports different levels of reports.
+By default the platform driver does not report anything. But when adding a
+report node:
+
+!
+!
+
+it is possible to enable either a devices and/or config report. The first will
+open up a Report session to dynamically report all accessible devices and its
+state. Whereby the second report states the currently active configuration of
+the platform driver.
diff --git a/repos/os/src/drivers/platform/device.cc b/repos/os/src/drivers/platform/device.cc
index c0adf9a25d..80446a6cfd 100644
--- a/repos/os/src/drivers/platform/device.cc
+++ b/repos/os/src/drivers/platform/device.cc
@@ -79,11 +79,15 @@ void Driver::Device::acquire(Session_component & sc)
});
sc.update_devices_rom();
+ sc.devices().update_report();
}
void Driver::Device::release(Session_component & sc)
{
+ if (!(_owner == sc))
+ return;
+
_reset_domain_list.for_each([&] (Reset_domain & r)
{
sc.devices().resets().apply(r.name, [&] (Driver::Reset &reset) {
@@ -102,15 +106,18 @@ void Driver::Device::release(Session_component & sc)
clock.disable(); });
});
- if (_owner == sc) _owner = Owner();
+ _owner = Owner();
+ sc.update_devices_rom();
+ sc.devices().update_report();
}
-void Driver::Device::report(Xml_generator & xml, Session_component & sc)
+void Driver::Device::report(Xml_generator & xml, Device_model & devices)
{
xml.node("device", [&] () {
xml.attribute("name", name());
xml.attribute("type", type());
+ xml.attribute("used", _owner.valid());
_io_mem_list.for_each([&] (Io_mem & io_mem) {
xml.node("io_mem", [&] () {
xml.attribute("phys_addr", String<16>(Hex(io_mem.range.start)));
@@ -135,7 +142,7 @@ void Driver::Device::report(Xml_generator & xml, Session_component & sc)
});
});
_clock_list.for_each([&] (Clock &c) {
- sc.devices().clocks().apply(c.name, [&] (Driver::Clock &clock) {
+ devices.clocks().apply(c.name, [&] (Driver::Clock &clock) {
xml.node("clock", [&] () {
xml.attribute("rate", clock.rate().value);
xml.attribute("name", c.driver_name);
@@ -143,7 +150,7 @@ void Driver::Device::report(Xml_generator & xml, Session_component & sc)
});
});
- _report_platform_specifics(xml, sc);
+ _report_platform_specifics(xml, devices);
});
}
@@ -157,3 +164,21 @@ Driver::Device::~Device()
if (_owner.valid()) {
error("Device to be destroyed, still obtained by session"); }
}
+
+
+void Driver::Device_model::update_report()
+{
+ if (_reporter.enabled()) {
+ Reporter::Xml_generator xml(_reporter, [&] () {
+ for_each([&] (Device & device) {
+ device.report(xml, *this); });
+ });
+ }
+}
+
+
+void Driver::Device_model::update(Xml_node const & node)
+{
+ _model.update_from_xml(*this, node);
+ update_report();
+}
diff --git a/repos/os/src/drivers/platform/device.h b/repos/os/src/drivers/platform/device.h
index ff0a3fa249..728ed3c329 100644
--- a/repos/os/src/drivers/platform/device.h
+++ b/repos/os/src/drivers/platform/device.h
@@ -16,6 +16,7 @@
#include
#include
+#include
#include
#include
#include
@@ -166,12 +167,12 @@ class Driver::Device : private List_model::Element
fn(idx++, ipr.addr, ipr.size); });
}
- void report(Xml_generator &, Session_component &);
+ void report(Xml_generator &, Device_model &);
protected:
virtual void _report_platform_specifics(Xml_generator &,
- Session_component &) {}
+ Device_model &) {}
friend class Driver::Device_model;
friend class List_model;
@@ -202,6 +203,7 @@ class Driver::Device_model :
private:
Heap & _heap;
+ Reporter & _reporter;
List_model _model { };
Clocks _clocks { };
Resets _resets { };
@@ -209,12 +211,11 @@ class Driver::Device_model :
public:
- void update(Xml_node const & node) {
- _model.update_from_xml(*this, node);
- }
+ void update_report();
+ void update(Xml_node const & node);
- Device_model(Heap & heap)
- : _heap(heap) { }
+ Device_model(Heap & heap, Reporter & reporter)
+ : _heap(heap), _reporter(reporter) { }
~Device_model() {
_model.destroy_all_elements(*this); }
diff --git a/repos/os/src/drivers/platform/main.cc b/repos/os/src/drivers/platform/main.cc
index 1747cb71a0..89a3b50ab2 100644
--- a/repos/os/src/drivers/platform/main.cc
+++ b/repos/os/src/drivers/platform/main.cc
@@ -21,15 +21,17 @@ struct Driver::Main
void update();
Env & env;
- Heap heap { env.ram(), env.rm() };
- Sliced_heap sliced_heap { env.ram(), env.rm() };
- Attached_rom_dataspace config_rom { env, "config" };
- Attached_rom_dataspace devices_rom { env, "devices" };
- Device_model devices { heap };
- Signal_handler handler { env.ep(), *this,
- &Main::update };
- Driver::Root root { env, sliced_heap,
- config_rom, devices };
+ Heap heap { env.ram(), env.rm() };
+ Sliced_heap sliced_heap { env.ram(), env.rm() };
+ Attached_rom_dataspace config_rom { env, "config" };
+ Attached_rom_dataspace devices_rom { env, "devices" };
+ Reporter cfg_reporter { env, "config" };
+ Reporter dev_reporter { env, "devices" };
+ Device_model devices { heap, dev_reporter };
+ Signal_handler handler { env.ep(), *this,
+ &Main::update };
+ Driver::Root root { env, sliced_heap,
+ config_rom, devices };
Main(Genode::Env & e)
: env(e)
@@ -46,8 +48,22 @@ void Driver::Main::update()
{
config_rom.update();
devices_rom.update();
+
+ config_rom.xml().for_each_sub_node("report", [&] (Xml_node const node) {
+ dev_reporter.enabled(node.attribute_value("devices", false));
+ cfg_reporter.enabled(node.attribute_value("config", false));
+ });
+
devices.update(devices_rom.xml());
root.update_policy();
+
+ if (cfg_reporter.enabled()) {
+ Reporter::Xml_generator xml(cfg_reporter, [&] () {
+ config_rom.xml().with_raw_content([&] (char const *src, size_t len) {
+ xml.append(src, len);
+ });
+ });
+ }
}
void Component::construct(Genode::Env &env) {
diff --git a/repos/os/src/drivers/platform/session_component.cc b/repos/os/src/drivers/platform/session_component.cc
index 5831eee2a5..6af99fa901 100644
--- a/repos/os/src/drivers/platform/session_component.cc
+++ b/repos/os/src/drivers/platform/session_component.cc
@@ -104,7 +104,7 @@ void Session_component::produce_xml(Xml_generator &xml)
xml.attribute("version", _version);
_devices.for_each([&] (Device & dev) {
- if (matches(dev)) dev.report(xml, *this); });
+ if (matches(dev)) dev.report(xml, _devices); });
}
diff --git a/repos/os/src/test/platform_drv/main.cc b/repos/os/src/test/platform_drv/main.cc
index ceeefa04b8..522ea5421a 100644
--- a/repos/os/src/test/platform_drv/main.cc
+++ b/repos/os/src/test/platform_drv/main.cc
@@ -96,6 +96,12 @@ struct Main
Reporter::Xml_generator cfg(config_reporter, [&] ()
{
+ cfg.node("report", [&]
+ {
+ cfg.attribute("devices", true);
+ cfg.attribute("config", true);
+ });
+
cfg.node("policy", [&]
{
cfg.attribute("label", "test-platform_drv -> ");