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 -> ");