platform_drv: attach reserved memory to device PD

Consumes the information about reserved memory region reports from
the devices ROM, and adds appropriated mappings to the corresponding
device PD.

Ref genodelabs/genode#4578
This commit is contained in:
Stefan Kalkowski 2022-09-15 11:28:29 +02:00 committed by Christian Helmuth
parent 85dc2e5b9b
commit 5e42f347d8
4 changed files with 100 additions and 13 deletions

View File

@ -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<Device>::Element
bridge(bridge) {}
};
struct Reserved_memory : List_model<Reserved_memory>::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<Device>::Element
});
}
template <typename FN>
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<Device>::Element
friend class List_model<Device>;
friend class List<Device>;
Env & _env;
Device_model & _model;
Name const _name;
Type const _type;
Owner _owner {};
List_model<Io_mem> _io_mem_list {};
List_model<Irq> _irq_list {};
List_model<Io_port_range> _io_port_range_list {};
List_model<Property> _property_list {};
List_model<Clock> _clock_list {};
List_model<Power_domain> _power_domain_list {};
List_model<Reset_domain> _reset_domain_list {};
List_model<Pci_config> _pci_config_list {};
Env & _env;
Device_model & _model;
Name const _name;
Type const _type;
Owner _owner {};
List_model<Io_mem> _io_mem_list {};
List_model<Irq> _irq_list {};
List_model<Io_port_range> _io_port_range_list {};
List_model<Property> _property_list {};
List_model<Clock> _clock_list {};
List_model<Power_domain> _power_domain_list {};
List_model<Reset_domain> _reset_domain_list {};
List_model<Pci_config> _pci_config_list {};
List_model<Reserved_memory> _reserved_mem_list {};
/*
* Noncopyable
@ -633,4 +652,39 @@ struct Driver::Pci_config_update_policy
}
};
struct Driver::Reserved_memory_update_policy
: Genode::List_model<Device::Reserved_memory>::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_ */

View File

@ -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<Device_component> & 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;

View File

@ -123,6 +123,7 @@ class Driver::Device_component : public Rpc_object<Platform::Device_interface,
Registry<Irq> _irq_registry {};
Registry<Io_mem> _io_mem_registry {};
Registry<Io_port_range> _io_port_range_registry {};
Registry<Io_mem> _reserved_mem_registry {};
Constructible<Pci_config> _pci_config {};
void _release_resources();

View File

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