diff --git a/repos/os/src/drivers/platform/device.h b/repos/os/src/drivers/platform/device.h index 8c631c6ca1..979bafb7cb 100644 --- a/repos/os/src/drivers/platform/device.h +++ b/repos/os/src/drivers/platform/device.h @@ -44,6 +44,7 @@ namespace Driver { struct Reset_domain_update_policy; struct Power_domain_update_policy; struct Pci_config_update_policy; + struct Reserved_memory_update_policy; } @@ -197,6 +198,15 @@ class Driver::Device : private List_model::Element bridge(bridge) {} }; + struct Reserved_memory : List_model::Element + { + using Range = Platform::Device_interface::Range; + + Range range; + + Reserved_memory(Range range) : range(range) {} + }; + Device(Env & env, Device_model & model, Name name, Type type); virtual ~Device(); @@ -245,6 +255,14 @@ class Driver::Device : private List_model::Element }); } + template + void for_each_reserved_memory(FN const & fn) const + { + unsigned idx = 0; + _reserved_mem_list.for_each([&] (Reserved_memory const & mem) { + fn(idx++, mem.range); }); + } + void generate(Xml_generator &, bool) const; protected: @@ -253,19 +271,20 @@ class Driver::Device : private List_model::Element friend class List_model; friend class List; - Env & _env; - Device_model & _model; - Name const _name; - Type const _type; - Owner _owner {}; - List_model _io_mem_list {}; - List_model _irq_list {}; - List_model _io_port_range_list {}; - List_model _property_list {}; - List_model _clock_list {}; - List_model _power_domain_list {}; - List_model _reset_domain_list {}; - List_model _pci_config_list {}; + Env & _env; + Device_model & _model; + Name const _name; + Type const _type; + Owner _owner {}; + List_model _io_mem_list {}; + List_model _irq_list {}; + List_model _io_port_range_list {}; + List_model _property_list {}; + List_model _clock_list {}; + List_model _power_domain_list {}; + List_model _reset_domain_list {}; + List_model _pci_config_list {}; + List_model _reserved_mem_list {}; /* * Noncopyable @@ -633,4 +652,39 @@ struct Driver::Pci_config_update_policy } }; + +struct Driver::Reserved_memory_update_policy +: Genode::List_model::Update_policy +{ + Genode::Allocator & alloc; + + Reserved_memory_update_policy(Genode::Allocator & alloc) : alloc(alloc) {} + + void destroy_element(Element & pd) { + Genode::destroy(alloc, &pd); } + + Element & create_element(Genode::Xml_node node) + { + using namespace Pci; + + addr_t addr = node.attribute_value("address", 0UL); + size_t size = node.attribute_value("size", 0UL); + return *(new (alloc) Element({addr, size})); + } + + void update_element(Element &, Genode::Xml_node) {} + + static bool element_matches_xml_node(Element const & e, Genode::Xml_node node) + { + addr_t addr = node.attribute_value("address", 0UL); + size_t size = node.attribute_value("size", 0UL); + return addr == e.range.start && size == e.range.size; + } + + static bool node_is_element(Genode::Xml_node node) + { + return node.has_type("reserved_memory"); + } +}; + #endif /* _SRC__DRIVERS__PLATFORM__DEVICE_H_ */ diff --git a/repos/os/src/drivers/platform/device_component.cc b/repos/os/src/drivers/platform/device_component.cc index 5733249c45..bed1211299 100644 --- a/repos/os/src/drivers/platform/device_component.cc +++ b/repos/os/src/drivers/platform/device_component.cc @@ -27,6 +27,14 @@ void Driver::Device_component::_release_resources() _irq_registry.for_each([&] (Irq & irq) { destroy(_session.heap(), &irq); }); + _io_port_range_registry.for_each([&] (Io_port_range & iop) { + destroy(_session.heap(), &iop); }); + + _reserved_mem_registry.for_each([&] (Io_mem & iomem) { + destroy(_session.heap(), &iomem); }); + + if (_pci_config.constructed()) _pci_config.destruct(); + _session.ram_quota_guard().replenish(Ram_quota{_ram_quota}); _session.cap_quota_guard().replenish(Cap_quota{_cap_quota}); } @@ -177,6 +185,20 @@ Device_component::Device_component(Registry & registry, _cap_quota += Io_mem_session::CAP_QUOTA; _pci_config.construct(cfg.addr); }); + + device.for_each_reserved_memory([&] (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; + Io_mem & iomem = *(new (session.heap()) + Io_mem(_reserved_mem_registry, idx, range)); + iomem.io_mem.construct(_env, iomem.range.start, + iomem.range.size, false); + session.device_pd().attach_dma_mem(iomem.io_mem->dataspace(), + iomem.range.start); + }); } catch(...) { _release_resources(); throw; diff --git a/repos/os/src/drivers/platform/device_component.h b/repos/os/src/drivers/platform/device_component.h index ce1a5e4f97..b65f28c480 100644 --- a/repos/os/src/drivers/platform/device_component.h +++ b/repos/os/src/drivers/platform/device_component.h @@ -123,6 +123,7 @@ class Driver::Device_component : public Rpc_object _irq_registry {}; Registry _io_mem_registry {}; Registry _io_port_range_registry {}; + Registry _reserved_mem_registry {}; Constructible _pci_config {}; void _release_resources(); diff --git a/repos/os/src/drivers/platform/device_model_policy.cc b/repos/os/src/drivers/platform/device_model_policy.cc index 0ddf15c9a8..45a04d8321 100644 --- a/repos/os/src/drivers/platform/device_model_policy.cc +++ b/repos/os/src/drivers/platform/device_model_policy.cc @@ -58,6 +58,11 @@ void Device_model::destroy_element(Device & device) device._pci_config_list.destroy_all_elements(policy); } + { + Reserved_memory_update_policy policy(_heap); + device._reserved_mem_list.destroy_all_elements(policy); + } + Genode::destroy(_heap, &device); } @@ -112,4 +117,9 @@ void Device_model::update_element(Device & device, Pci_config_update_policy policy(_heap); device._pci_config_list.update_from_xml(policy, node); } + + { + Reserved_memory_update_policy policy(_heap); + device._reserved_mem_list.update_from_xml(policy, node); + } }