diff --git a/repos/os/src/drivers/platform/rpi/rpi_device.cc b/repos/os/src/drivers/platform/rpi/rpi_device.cc index 92f2e4a893..bbf7f359f3 100644 --- a/repos/os/src/drivers/platform/rpi/rpi_device.cc +++ b/repos/os/src/drivers/platform/rpi/rpi_device.cc @@ -34,21 +34,17 @@ unsigned Driver::Rpi_device::Power_domain::id() }; -bool Driver::Rpi_device::acquire(Driver::Session_component & sc) +void Driver::Rpi_device::acquire(Driver::Session_component & sc) { - bool ret = Driver::Device::acquire(sc); + Driver::Device::acquire(sc); - if (ret) { - _power_domain_list.for_each([&] (Power_domain & p) { - auto & msg = sc.env().mbox.message(); - msg.append_no_response(p.id(), - true, - true); - sc.env().mbox.call(); - }); - } - - return ret; + _power_domain_list.for_each([&] (Power_domain & p) { + auto & msg = sc.env().mbox.message(); + msg.append_no_response(p.id(), + true, + true); + sc.env().mbox.call(); + }); } diff --git a/repos/os/src/drivers/platform/rpi/rpi_device.h b/repos/os/src/drivers/platform/rpi/rpi_device.h index 2e93a323f1..fe738fd16c 100644 --- a/repos/os/src/drivers/platform/rpi/rpi_device.h +++ b/repos/os/src/drivers/platform/rpi/rpi_device.h @@ -39,7 +39,7 @@ class Driver::Rpi_device : public Driver::Device unsigned id(); }; - bool acquire(Session_component &) override; + void acquire(Session_component &) override; void release(Session_component &) override; Rpi_device(Device::Name name, Device::Type type) diff --git a/repos/os/src/drivers/platform/spec/arm/device.cc b/repos/os/src/drivers/platform/spec/arm/device.cc index 385a06828b..216267d11e 100644 --- a/repos/os/src/drivers/platform/spec/arm/device.cc +++ b/repos/os/src/drivers/platform/spec/arm/device.cc @@ -12,114 +12,29 @@ */ #include +#include #include + +Driver::Device::Owner::Owner(Session_component & session) +: obj_id(reinterpret_cast(&session)) {} + + Driver::Device::Name Driver::Device::name() const { return _name; } Driver::Device::Type Driver::Device::type() const { return _type; } -bool Driver::Device::acquire(Session_component & sc) -{ - if (_session.valid() && _session != sc.label()) { return false; } - - /** - * FIXME: By now, we cannot use the connection objects for IRQ and - * IOMEM and propagate missing resources when opening the - * sessions, because the combination of Genode::Env and - * Genode::Connection object transparently does quota upgrades. - * If we like to account those costs per client, we actually - * need to explicitely forward exceptions during session - * requests. - * For now, we try to measure the probable costs. - */ - Cap_quota_guard::Reservation caps(sc.cap_quota_guard(), - Cap_quota{_cap_quota_required()}); - Ram_quota_guard::Reservation ram(sc.ram_quota_guard(), - Ram_quota{_ram_quota_required()}); - - _session = sc.label(); - - caps.acknowledge(); - ram.acknowledge(); - return true; -} +Driver::Device::Owner Driver::Device::owner() const { return _owner; } -void Driver::Device::release(Session_component & sc) -{ - if (_session != sc.label()) { return; } - - _io_mem_list.for_each([&] (Io_mem & io_mem) { - if (io_mem.io_mem) { - destroy(sc.heap(), io_mem.io_mem); - io_mem.io_mem = nullptr; - } - }); - - _irq_list.for_each([&] (Irq & irq) { - if (irq.irq) { - destroy(sc.heap(), irq.irq); - irq.irq = nullptr; - } - }); - - _session = Platform::Session::Label();; - - sc.replenish(Cap_quota{_cap_quota_required()}); - sc.replenish(Ram_quota{_ram_quota_required()}); -} +void Driver::Device::acquire(Session_component & sc) { + if (!_owner.valid()) _owner = sc; } -Genode::Irq_session_capability Driver::Device::irq(unsigned idx, - Session_component & sc) -{ - Irq_session_capability cap; - - if (_session != sc.label()) { return cap; } - - unsigned i = 0; - _irq_list.for_each([&] (Irq & irq) - { - if (i++ != idx) return; - - if (!irq.irq) { - irq.irq = new (sc.heap()) - Irq_connection(sc.env().env, irq.number); - } - cap = irq.irq->cap(); - }); - - return cap; -} - - -Genode::Io_mem_session_capability -Driver::Device::io_mem(unsigned idx, Range &range, Cache cache, Session_component & sc) -{ - Io_mem_session_capability cap; - - if (_session != sc.label()) return cap; - - unsigned i = 0; - _io_mem_list.for_each([&] (Io_mem & io_mem) - { - if (i++ != idx) return; - - range = Range { .start = io_mem.base & 0xfff, - .size = io_mem.size }; - - if (!io_mem.io_mem) { - io_mem.io_mem = new (sc.heap()) - Io_mem_connection(sc.env().env, io_mem.base, io_mem.size, - (cache == WRITE_COMBINED)); - } - cap = io_mem.io_mem->cap(); - }); - - return cap; -} +void Driver::Device::release(Session_component & sc) { + if (_owner == sc) _owner = Owner();; } void Driver::Device::report(Xml_generator & xml, Session_component & sc) @@ -129,8 +44,8 @@ void Driver::Device::report(Xml_generator & xml, Session_component & sc) xml.attribute("type", type()); _io_mem_list.for_each([&] (Io_mem & io_mem) { xml.node("io_mem", [&] () { - xml.attribute("phys_addr", String<16>(Hex(io_mem.base))); - xml.attribute("size", String<16>(Hex(io_mem.size))); + xml.attribute("phys_addr", String<16>(Hex(io_mem.range.start))); + xml.attribute("size", String<16>(Hex(io_mem.range.size))); }); }); _irq_list.for_each([&] (Irq & irq) { @@ -149,36 +64,12 @@ void Driver::Device::report(Xml_generator & xml, Session_component & sc) } -Genode::size_t Driver::Device::_cap_quota_required() -{ - /* one cap is needed for the device component itself */ - size_t total = 1; - _io_mem_list.for_each([&] (Io_mem &) { - total += Io_mem_session::CAP_QUOTA; }); - _irq_list.for_each([&] (Irq &) { - total += Irq_session::CAP_QUOTA; }); - return total; -} - - -Genode::size_t Driver::Device::_ram_quota_required() -{ - size_t total = 0; - _io_mem_list.for_each([&] (Io_mem &) { - total += Io_mem_session::RAM_QUOTA; }); - _irq_list.for_each([&] (Irq &) { - total += Irq_session::RAM_QUOTA; }); - return total; -} - - Driver::Device::Device(Name name, Type type) : _name(name), _type(type) { } Driver::Device::~Device() { - if (_session.valid()) { - error("Device to be destroyed, still obtained by session ", - _session); } + if (_owner.valid()) { + error("Device to be destroyed, still obtained by session"); } } diff --git a/repos/os/src/drivers/platform/spec/arm/device.h b/repos/os/src/drivers/platform/spec/arm/device.h index 0ab675fbd5..f4bf840a89 100644 --- a/repos/os/src/drivers/platform/spec/arm/device.h +++ b/repos/os/src/drivers/platform/spec/arm/device.h @@ -15,8 +15,6 @@ #define _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_ #include -#include -#include #include #include #include @@ -41,20 +39,34 @@ class Driver::Device : private List_model::Element { public: + using Name = Genode::String<64>; + using Type = Genode::String<64>; + using Range = Platform::Device_interface::Range; + + struct Owner + { + void * obj_id; + + Owner() : obj_id(nullptr) {} + Owner(Session_component & session); + + bool operator == (Owner const & o) const { + return obj_id == o.obj_id; } + + bool valid() const { + return obj_id != nullptr; } + }; + struct Io_mem : List_model::Element { - addr_t base; - size_t size; - Io_mem_connection * io_mem { nullptr }; + Range range; - Io_mem(addr_t base, size_t size) - : base(base), size(size) {} + Io_mem(Range range) : range(range) {} }; struct Irq : List_model::Element { - unsigned number; - Irq_connection * irq { nullptr }; + unsigned number; Irq(unsigned number) : number(number) {} }; @@ -71,22 +83,29 @@ class Driver::Device : private List_model::Element : name(name), value(value) {} }; - using Name = Genode::String<64>; - using Type = Genode::String<64>; - using Range = Platform::Device_interface::Range; - Device(Name name, Type type); virtual ~Device(); - Name name() const; - Type type() const; + Name name() const; + Type type() const; + Owner owner() const; - virtual bool acquire(Session_component &); + virtual void acquire(Session_component &); virtual void release(Session_component &); - Irq_session_capability irq(unsigned idx, Session_component &); - Io_mem_session_capability io_mem(unsigned idx, Range &, Cache, - Session_component &); + template void for_each_irq(FN const & fn) + { + unsigned idx = 0; + _irq_list.for_each([&] (Irq const & irq) { + fn(idx++, irq.number); }); + } + + template void for_each_io_mem(FN const & fn) + { + unsigned idx = 0; + _io_mem_list.for_each([&] (Io_mem const & iomem) { + fn(idx++, iomem.range); }); + } void report(Xml_generator &, Session_component &); @@ -95,19 +114,16 @@ class Driver::Device : private List_model::Element virtual void _report_platform_specifics(Xml_generator &, Session_component &) {} - size_t _cap_quota_required(); - size_t _ram_quota_required(); - friend class Driver::Device_model; friend class List_model; friend class List; - Name _name; - Type _type; - Platform::Session::Label _session {}; - List_model _io_mem_list {}; - List_model _irq_list {}; - List_model _property_list {}; + Name _name; + Type _type; + Owner _owner {}; + List_model _io_mem_list {}; + List_model _irq_list {}; + List_model _property_list {}; /* * Noncopyable @@ -201,18 +217,18 @@ struct Driver::Io_mem_update_policy : Genode::List_model::Update Element & create_element(Genode::Xml_node node) { - Genode::addr_t base = node.attribute_value("address", 0); - Genode::size_t size = node.attribute_value("size", 0); - return *(new (alloc) Element(base, size)); + Device::Range range { node.attribute_value("address", 0), + node.attribute_value("size", 0) }; + return *(new (alloc) Element(range)); } void update_element(Element &, Genode::Xml_node) {} static bool element_matches_xml_node(Element const & iomem, Genode::Xml_node node) { - Genode::addr_t base = node.attribute_value("address", 0); - Genode::size_t size = node.attribute_value("size", 0); - return (base == iomem.base) && (size == iomem.size); + Device::Range range { node.attribute_value("address", 0), + node.attribute_value("size", 0) }; + return (range.start == iomem.range.start) && (range.size == iomem.range.size); } static bool node_is_element(Genode::Xml_node node) diff --git a/repos/os/src/drivers/platform/spec/arm/device_component.cc b/repos/os/src/drivers/platform/spec/arm/device_component.cc index 2f4e475631..f4ac1c7751 100644 --- a/repos/os/src/drivers/platform/spec/arm/device_component.cc +++ b/repos/os/src/drivers/platform/spec/arm/device_component.cc @@ -17,36 +17,47 @@ using Driver::Device_component; + +void Driver::Device_component::_release_resources() +{ + _io_mem_registry.for_each([&] (Io_mem & iomem) { + destroy(_session.heap(), &iomem); }); + + _irq_registry.for_each([&] (Irq & irq) { + destroy(_session.heap(), &irq); }); + + _session.ram_quota_guard().replenish(Ram_quota{_ram_quota}); + _session.cap_quota_guard().replenish(Cap_quota{_cap_quota}); +} + + Driver::Device::Name Device_component::device() const { return _device; } Driver::Session_component & Device_component::session() { return _session; } -bool Driver::Device_component::acquire() -{ - bool acquired = false; - _session.env().devices.for_each([&] (Driver::Device & device) { - if (device.name() == _device) { - acquired = device.acquire(_session); }}); - return acquired; -} - - -void Driver::Device_component::release() -{ - _session.env().devices.for_each([&] (Driver::Device & device) { - if (device.name() == _device) { device.release(_session); }}); -} - - Genode::Io_mem_session_capability Device_component::io_mem(unsigned idx, Range &range, Cache cache) { Io_mem_session_capability cap; - _session.env().devices.for_each([&] (Driver::Device & device) { - if (device.name() == _device) { - cap = device.io_mem(idx, range, cache, _session); }}); + + _io_mem_registry.for_each([&] (Io_mem & iomem) + { + if (iomem.idx != idx) + return; + + if (!iomem.io_mem.constructed()) + iomem.io_mem.construct(_session.env().env, + iomem.range.start, + iomem.range.size, + cache == WRITE_COMBINED); + + range = iomem.range; + range.start &= 0xfff; + cap = iomem.io_mem->cap(); + }); + return cap; } @@ -54,22 +65,64 @@ Device_component::io_mem(unsigned idx, Range &range, Cache cache) Genode::Irq_session_capability Device_component::irq(unsigned idx) { Irq_session_capability cap; - _session.env().devices.for_each([&] (Driver::Device & device) { - if (device.name() == _device) { cap = device.irq(idx, _session); }}); + + _irq_registry.for_each([&] (Irq & irq) + { + if (irq.idx != idx) + return; + + if (!irq.irq.constructed()) + irq.irq.construct(_session.env().env, irq.number); + + cap = irq.irq->cap(); + }); + return cap; } -void Driver::Device_component::report(Xml_generator & xml) +Device_component::Device_component(Registry & registry, + Driver::Session_component & session, + Driver::Device & device) +: _session(session), _device(device.name()), _reg_elem(registry, *this) { - _session.env().devices.for_each([&] (Driver::Device & device) { - if (device.name() == _device) { device.report(xml, _session); }}); + session.cap_quota_guard().withdraw(Cap_quota{1}); + _cap_quota += 1; + + /** + * FIXME: By now, we cannot use the connection objects for IRQ and + * IOMEM and propagate missing resources when opening the + * sessions, because the combination of Genode::Env and + * Genode::Connection object transparently does quota upgrades. + * If we like to account those costs per client, we actually + * need to explicitely forward exceptions during session + * requests. + * For now, we try to measure the probable costs. + */ + + try { + device.for_each_irq([&] (unsigned idx, unsigned nr) + { + session.ram_quota_guard().withdraw(Ram_quota{Irq_session::RAM_QUOTA}); + _ram_quota += Irq_session::RAM_QUOTA; + session.cap_quota_guard().withdraw(Cap_quota{Irq_session::CAP_QUOTA}); + _cap_quota += Irq_session::CAP_QUOTA; + new (session.heap()) Irq(_irq_registry, idx, nr); + }); + + device.for_each_io_mem([&] (unsigned idx, Range range) + { + session.ram_quota_guard().withdraw(Ram_quota{Io_mem_session::RAM_QUOTA}); + _ram_quota += Io_mem_session::RAM_QUOTA; + session.cap_quota_guard().withdraw(Cap_quota{Io_mem_session::CAP_QUOTA}); + _cap_quota += Io_mem_session::CAP_QUOTA; + new (session.heap()) Io_mem(_io_mem_registry, idx, range); + }); + } catch(...) { + _release_resources(); + throw; + } } -Device_component::Device_component(Driver::Session_component & session, - Driver::Device::Name const device) -: _session(session), _device(device) { } - - -Device_component::~Device_component() { release(); } +Device_component::~Device_component() { _release_resources(); }; diff --git a/repos/os/src/drivers/platform/spec/arm/device_component.h b/repos/os/src/drivers/platform/spec/arm/device_component.h index 6726954e7e..1c045bded0 100644 --- a/repos/os/src/drivers/platform/spec/arm/device_component.h +++ b/repos/os/src/drivers/platform/spec/arm/device_component.h @@ -14,9 +14,13 @@ #ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_COMPONENT_H_ #define _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_COMPONENT_H_ +#include #include -#include +#include +#include #include +#include +#include #include #include @@ -32,18 +36,42 @@ class Driver::Device_component : public Rpc_object::Element + { + unsigned idx; + unsigned number; + Constructible irq {}; + + Irq(Registry & registry, + unsigned idx, + unsigned number) + : + Registry::Element(registry, *this), + idx(idx), number(number) {} + }; + + struct Io_mem : Registry::Element + { + unsigned idx; + Range range; + Constructible io_mem {}; + + Io_mem(Registry & registry, + unsigned idx, + Range range) + : + Registry::Element(registry, *this), + idx(idx), range(range) {} + }; + + Device_component(Registry & registry, + Session_component & session, + Driver::Device & device); ~Device_component(); Driver::Device::Name device() const; Session_component & session(); - bool acquire(); - void release(); - - void report(Xml_generator&); - /************************************ ** Platform::Device RPC functions ** @@ -54,12 +82,15 @@ class Driver::Device_component : public Rpc_object::Element _reg_elem; + Registry _irq_registry {}; + Registry _io_mem_registry {}; - Session_component & _session; - Driver::Device::Name const _device; - Capability _cap {}; - List_element _list_elem { this }; + void _release_resources(); /* * Noncopyable diff --git a/repos/os/src/drivers/platform/spec/arm/main.cc b/repos/os/src/drivers/platform/spec/arm/main.cc index eaa5189383..6a04c2885b 100644 --- a/repos/os/src/drivers/platform/spec/arm/main.cc +++ b/repos/os/src/drivers/platform/spec/arm/main.cc @@ -39,15 +39,8 @@ struct Driver::Main void Driver::Main::update_config() { env.config.update(); - - /** - * We must perform the policy update before updating the devices since - * the former may need to release devices and its corresponding Io_mem - * and Irq connections when closing a session that is no longer supposed - * to exist. For doing so, it must access the old device model. - */ - root.update_policy(); env.devices.update(env.config.xml()); + root.update_policy(); } void Component::construct(Genode::Env &env) { diff --git a/repos/os/src/drivers/platform/spec/arm/root.cc b/repos/os/src/drivers/platform/spec/arm/root.cc index 919f2c134f..f1c90503a4 100644 --- a/repos/os/src/drivers/platform/spec/arm/root.cc +++ b/repos/os/src/drivers/platform/spec/arm/root.cc @@ -13,32 +13,22 @@ #include +using Version = Driver::Session_component::Policy_version; + void Driver::Root::update_policy() { - _sessions.for_each([&] (Session_component & sc) { - - bool policy_changed = false; - unsigned device_count = 0; - + _sessions.for_each([&] (Session_component & sc) + { try { Session_policy const policy { sc._label, _env.config.xml() }; - - policy.for_each_sub_node("device", [&] (Xml_node node) { - device_count++; - if (!sc.has_device(node.attribute_value("name", - Device::Name()))) { - policy_changed = true; } - }); - - if (device_count != sc.devices_count()) { policy_changed = true; } + sc.update_policy(policy.attribute_value("info", false), + policy.attribute_value("version", Version())); } catch (Session_policy::No_policy_defined) { - policy_changed = true; error("No matching policy for '", sc._label.string(), "' anymore, will close the session!"); + close(sc.cap()); } - - if (policy_changed) { close(sc.cap()); } }); } @@ -55,10 +45,8 @@ Driver::Session_component * Driver::Root::_create_session(const char *args) Session_component(_env, _sessions, label, session_resources_from_args(args), session_diag_from_args(args), - policy.attribute_value("info", false)); - - policy.for_each_sub_node("device", [&] (Xml_node node) { - sc->add(node.attribute_value("name", Driver::Device::Name())); }); + policy.attribute_value("info", false), + policy.attribute_value("version", Version())); } catch (Session_policy::No_policy_defined) { error("Invalid session request, no matching policy for ", "'", label_from_args(args).string(), "'"); diff --git a/repos/os/src/drivers/platform/spec/arm/session_component.cc b/repos/os/src/drivers/platform/spec/arm/session_component.cc index 1860dcb249..08fd2fd840 100644 --- a/repos/os/src/drivers/platform/spec/arm/session_component.cc +++ b/repos/os/src/drivers/platform/spec/arm/session_component.cc @@ -18,11 +18,93 @@ using Driver::Session_component; + +Genode::Capability +Session_component::_acquire(Device & device) +{ + Device_component * dc = new (heap()) + Device_component(_device_registry, *this, device); + device.acquire(*this); + return _env.env.ep().rpc_ep().manage(dc); +}; + + +void Session_component::_release_device(Device_component & dc) +{ + Device::Name name = dc.device(); + _env.env.ep().rpc_ep().dissolve(&dc); + destroy(heap(), &dc); + + _env.devices.for_each([&] (Device & dev) { + if (name == dev.name()) dev.release(*this); }); +} + + +void Session_component::_free_dma_buffer(Dma_buffer & buf) +{ + Ram_dataspace_capability cap = buf.cap; + destroy(heap(), &buf); + _env_ram.free(cap); +} + + +bool Session_component::matches(Device & dev) const +{ + bool ret = false; + + try { + Session_policy const policy { label(), _env.config.xml() }; + policy.for_each_sub_node("device", [&] (Xml_node node) { + if (dev.name() == node.attribute_value("name", Device::Name())) + ret = true; + }); + } catch (Session_policy::No_policy_defined) { } + + return ret; +}; + + +void Session_component::update_policy(bool info, Policy_version version) +{ + _info = info; + _version = version; + + enum Device_state { AWAY, CHANGED, UNCHANGED }; + + _device_registry.for_each([&] (Device_component & dc) { + Device_state state = AWAY; + _env.devices.for_each([&] (Device & dev) { + if (dev.name() != dc.device()) + return; + state = (dev.owner() == _owner_id) ? UNCHANGED : CHANGED; + }); + + if (state == UNCHANGED) + return; + + if (state == AWAY) + warning("Device ", dc.device(), + " has changed, will close device session"); + else + warning("Device ", dc.device(), + " unavailable, will close device session"); + _release_device(dc); + }); + + update_devices_rom(); +}; + + void Session_component::produce_xml(Xml_generator &xml) { - if (!_info) { return; } - for (Device_list_element * e = _device_list.first(); e; e = e->next()) { - e->object()->report(xml); } + if (!_info) + return; + + if (_version.valid()) + xml.attribute("version", _version); + + _env.devices.for_each([&] (Device & dev) { + if (matches(dev)) dev.report(xml, *this); }); } @@ -32,39 +114,6 @@ Genode::Heap & Session_component::heap() { return _md_alloc; } Driver::Env & Session_component::env() { return _env; } -void Session_component::add(Device::Name const & device) -{ - if (has_device(device)) return; - - Device_component * new_dc = - new (_md_alloc) Device_component(*this, device); - - Device_list_element * last = nullptr; - for (last = _device_list.first(); last; last = last->next()) { - if (!last->next()) break; } - _device_list.insert(&new_dc->_list_elem, last); -} - - -bool Session_component::has_device(Device::Name const & device) const -{ - for (Device_list_element const * e = _device_list.first(); e; - e = e->next()) { - if (e->object()->device() == device) { return true; } - } - return false; -} - - -unsigned Session_component::devices_count() const -{ - unsigned counter = 0; - for (Device_list_element const * e = _device_list.first(); - e; e = e->next()) { counter++; } - return counter; -} - - void Session_component::update_devices_rom() { _rom_session.trigger_update(); @@ -78,40 +127,59 @@ Genode::Rom_session_capability Session_component::devices_rom() { Genode::Capability Session_component::acquire_device(Platform::Session::Device_name const &name) { - for (Device_list_element * e = _device_list.first(); e; e = e->next()) { - if (e->object()->device() != name.string()) { continue; } + Capability cap; - if (!e->object()->acquire()) { - error("Device ", e->object()->device(), - " already acquired!"); - break; - } + /* Search for existing, aquired device session */ + _device_registry.for_each([&] (Device_component & dc) { + if (dc.device() == name) + cap = dc.cap(); + }); - return _env.env.ep().rpc_ep().manage(e->object()); - } + if (cap.valid()) + return cap; - return Capability(); + _env.devices.for_each([&] (Device & dev) + { + if (dev.name() != name || !matches(dev)) + return; + if (dev.owner().valid()) + warning("Cannot aquire device ", name, " already in use"); + else + cap = _acquire(dev); + }); + + return cap; } Genode::Capability Session_component::acquire_single_device() { - Device_list_element * e = _device_list.first(); - if (!e) { return Capability(); } + Capability cap; - return acquire_device(e->object()->device()); + /* Search for existing, aquired device session */ + _device_registry.for_each([&] (Device_component & dc) { + cap = dc.cap(); }); + + if (cap.valid()) + return cap; + + _env.devices.for_each([&] (Device & dev) { + if (matches(dev) && !dev.owner().valid()) + cap = _acquire(dev); }); + + return cap; } void Session_component::release_device(Capability device_cap) { - _env.env.ep().rpc_ep().apply(device_cap, [&] (Device_component * dc) { - if (!dc) - return; - _env.env.ep().rpc_ep().dissolve(dc); - dc->release(); - }); + if (!device_cap.valid()) + return; + + _device_registry.for_each([&] (Device_component & dc) { + if (device_cap.local_name() == dc.cap().local_name()) + _release_device(dc); }); } @@ -123,7 +191,7 @@ Session_component::alloc_dma_buffer(size_t const size, Cache cache) if (!ram_cap.valid()) return ram_cap; try { - _buffer_list.insert(new (_md_alloc) Dma_buffer(ram_cap)); + new (heap()) Dma_buffer(_buffer_registry, ram_cap); } catch (Out_of_ram) { _env_ram.free(ram_cap); throw; @@ -140,44 +208,41 @@ void Session_component::free_dma_buffer(Ram_dataspace_capability ram_cap) { if (!ram_cap.valid()) { return; } - for (Dma_buffer * buf = _buffer_list.first(); buf; buf = buf->next()) { - - if (buf->cap.local_name() != ram_cap.local_name()) continue; - - _buffer_list.remove(buf); - destroy(_md_alloc, buf); - _env_ram.free(ram_cap); - return; - } + _buffer_registry.for_each([&] (Dma_buffer & buf) { + if (buf.cap.local_name() == ram_cap.local_name()) + _free_dma_buffer(buf); }); } Genode::addr_t Session_component::dma_addr(Ram_dataspace_capability ram_cap) { - if (!ram_cap.valid()) { return 0; } + addr_t ret = 0; - for (Dma_buffer * buf = _buffer_list.first(); buf; buf = buf->next()) { + if (!ram_cap.valid()) + return ret; - if (buf->cap.local_name() != ram_cap.local_name()) continue; + _buffer_registry.for_each([&] (Dma_buffer & buf) { + if (buf.cap.local_name() == ram_cap.local_name()) { + Dataspace_client dsc(buf.cap); + ret = dsc.phys_addr(); + } }); - Dataspace_client dsc(buf->cap); - return dsc.phys_addr(); - } - - return 0; + return ret; } -Session_component::Session_component(Driver::Env & env, - Session_registry & registry, - Label const & label, - Resources const & resources, - Diag const & diag, - bool const info) -: Session_object(env.env.ep(), resources, label, diag), - Session_registry::Element(registry, *this), - Dynamic_rom_session::Xml_producer("devices"), - _env(env), _info(info) +Session_component::Session_component(Driver::Env & env, + Session_registry & registry, + Label const & label, + Resources const & resources, + Diag const & diag, + bool const info, + Policy_version const version) +: + Session_object(env.env.ep(), resources, label, diag), + Session_registry::Element(registry, *this), + Dynamic_rom_session::Xml_producer("devices"), + _env(env), _info(info), _version(version) { /* * FIXME: As the ROM session does not propagate Out_of_* @@ -188,25 +253,21 @@ Session_component::Session_component(Driver::Env & env, * we account the costs here until the ROM session interface * changes. */ - _cap_quota_guard().withdraw(Cap_quota{1}); + _cap_quota_guard().withdraw(Cap_quota{Rom_session::CAP_QUOTA}); _ram_quota_guard().withdraw(Ram_quota{5*1024}); } Session_component::~Session_component() { - while (_device_list.first()) { - Device_list_element * e = _device_list.first(); - release_device(e->object()->cap()); - _device_list.remove(e); - destroy(_md_alloc, e->object()); - } + _device_registry.for_each([&] (Device_component & dc) { + _release_device(dc); }); - /* also free up dma buffers */ - while (_buffer_list.first()) - free_dma_buffer(_buffer_list.first()->cap); + /* free up dma buffers */ + _buffer_registry.for_each([&] (Dma_buffer & buf) { + _free_dma_buffer(buf); }); /* replenish quota for rom sessions, see constructor for explanation */ - _cap_quota_guard().replenish(Cap_quota{1}); + _cap_quota_guard().replenish(Cap_quota{Rom_session::CAP_QUOTA}); _ram_quota_guard().replenish(Ram_quota{5*1024}); } diff --git a/repos/os/src/drivers/platform/spec/arm/session_component.h b/repos/os/src/drivers/platform/spec/arm/session_component.h index cdcad9bbad..76f25a533a 100644 --- a/repos/os/src/drivers/platform/spec/arm/session_component.h +++ b/repos/os/src/drivers/platform/spec/arm/session_component.h @@ -40,26 +40,29 @@ class Driver::Session_component public: using Session_registry = Registry; + using Policy_version = String<64>; + + Session_component(Driver::Env & env, + Session_registry & registry, + Label const & label, + Resources const & resources, + Diag const & diag, + bool const info, + Policy_version const version); - Session_component(Driver::Env & env, - Session_registry & registry, - Label const & label, - Resources const & resources, - Diag const & diag, - bool const info); ~Session_component(); Heap & heap(); Driver::Env & env(); - void add(Device::Name const &); - bool has_device(Device::Name const &) const; - unsigned devices_count() const; - void update_devices_rom(); + bool matches(Device &) const; + void update_devices_rom(); Ram_quota_guard & ram_quota_guard() { return _ram_quota_guard(); } Cap_quota_guard & cap_quota_guard() { return _cap_quota_guard(); } + void update_policy(bool info, Policy_version version); + /************************** ** Platform Session API ** @@ -80,28 +83,32 @@ class Driver::Session_component friend class Root; - struct Dma_buffer : List::Element + struct Dma_buffer : Registry::Element { Ram_dataspace_capability const cap; - Dma_buffer(Ram_dataspace_capability const cap) - : cap(cap) {} + Dma_buffer(Registry & registry, + Ram_dataspace_capability const cap) + : Registry::Element(registry, *this), cap(cap) {} }; - using Device_list_element = List_element; - using Device_list = List; - - Driver::Env & _env; - Constrained_ram_allocator _env_ram { _env.env.pd(), - _ram_quota_guard(), - _cap_quota_guard() }; - Heap _md_alloc { _env_ram, _env.env.rm() }; - Device_list _device_list { }; - List _buffer_list { }; - Dynamic_rom_session _rom_session { _env.env.ep(), _env.env.ram(), - _env.env.rm(), *this }; - bool const _info; + Driver::Env & _env; + Device::Owner _owner_id { *this }; + Constrained_ram_allocator _env_ram { _env.env.pd(), + _ram_quota_guard(), + _cap_quota_guard() }; + Heap _md_alloc { _env_ram, _env.env.rm() }; + Registry _device_registry { }; + Registry _buffer_registry { }; + Dynamic_rom_session _rom_session { _env.env.ep(), _env.env.ram(), + _env.env.rm(), *this }; + bool _info; + Policy_version _version; + Device_capability _acquire(Device & device); + void _release_device(Device_component & dc); + void _free_dma_buffer(Dma_buffer & buf); + /* * Noncopyable */