platform: pass reserved memory update to IOMMU

Only add default mappings on IOMMU construction and on reserved-memory
updates.

Issue #5232
This commit is contained in:
Johannes Schlatow 2024-06-10 18:15:13 +02:00 committed by Norman Feske
parent 6912dd62fa
commit 0aafec038d
4 changed files with 56 additions and 31 deletions

View File

@ -90,6 +90,28 @@ class Driver::Common : Device_reporter,
void Driver::Common::acquire_io_mmu_devices()
{
auto init_default_mappings = [&] (Io_mmu & io_mmu_dev) {
_devices.for_each([&] (Device const & device) {
device.with_optional_io_mmu(io_mmu_dev.name(), [&] () {
bool has_reserved_mem = false;
device.for_each_reserved_memory([&] (unsigned,
Io_mmu::Range range) {
io_mmu_dev.add_default_range(range, range.start);
has_reserved_mem = true;
});
if (!has_reserved_mem)
return;
/* enable default mappings for corresponding pci devices */
device.for_pci_config([&] (Device::Pci_config const & cfg) {
io_mmu_dev.enable_default_mappings(
{cfg.bus_num, cfg.dev_num, cfg.func_num});
});
});
});
};
_io_mmu_factories.for_each([&] (Io_mmu_factory & factory) {
_devices.for_each([&] (Device & dev) {
@ -99,6 +121,11 @@ void Driver::Common::acquire_io_mmu_devices()
if (factory.matches(dev)) {
dev.acquire(*this);
factory.create(_heap, _io_mmu_devices, dev);
_io_mmu_devices.for_each([&] (Io_mmu & io_mmu_dev) {
if (io_mmu_dev.name() == dev.name())
init_default_mappings(io_mmu_dev);
});
}
});
@ -117,31 +144,6 @@ void Driver::Common::acquire_io_mmu_devices()
if (device_present && !mpu_present)
_root.enable_dma_remapping();
/* iterate devices and add default mappings */
_devices.for_each([&] (Device & device) {
device.for_each_io_mmu([&] (Device::Io_mmu const & io_mmu) {
_io_mmu_devices.for_each([&] (Io_mmu & io_mmu_dev) {
if (io_mmu_dev.name() == io_mmu.name) {
bool has_reserved_mem = false;
device.for_each_reserved_memory([&] (unsigned,
Io_mmu::Range range) {
io_mmu_dev.add_default_range(range, range.start);
has_reserved_mem = true;
});
if (!has_reserved_mem)
return;
/* enable default mappings for corresponding pci devices */
device.for_pci_config([&] (Device::Pci_config const & cfg) {
io_mmu_dev.enable_default_mappings(
{cfg.bus_num, cfg.dev_num, cfg.func_num});
});
}
});
}, [&] () { /* empty list fn */ });
});
bool kernel_iommu_present { false };
_io_mmu_devices.for_each([&] (Io_mmu & io_mmu_dev) {
io_mmu_dev.default_mappings_complete();

View File

@ -417,6 +417,15 @@ class Driver::Device : private List_model<Device>::Element
empty_fn();
}
template <typename FN>
void with_optional_io_mmu(Io_mmu::Name const & name, FN && fn) const
{
_io_mmu_list.for_each([&] (Io_mmu const & io_mmu) {
if (io_mmu.name == name)
fn();
});
}
void generate(Xml_generator &, bool) const;
void update(Allocator &, Xml_node const &, Reserved_memory_handler &);

View File

@ -76,6 +76,18 @@ void Driver::Root::add_range(Device const & dev, Range const & range)
sc._dma_allocator.reserve(range.start, range.size);
});
/* add default mapping and enable for corresponding pci device */
_io_mmu_devices.for_each([&] (Io_mmu & io_mmu_dev) {
dev.with_optional_io_mmu(io_mmu_dev.name(), [&] () {
io_mmu_dev.add_default_range(range, range.start);
dev.for_pci_config([&] (Device::Pci_config const & cfg) {
io_mmu_dev.enable_default_mappings(
{cfg.bus_num, cfg.dev_num, cfg.func_num});
});
});
});
}
@ -85,6 +97,12 @@ void Driver::Root::remove_range(Device const & dev, Range const & range)
if (!sc.matches(dev)) return;
sc._dma_allocator.unreserve(range.start, range.size);
});
/*
* remark: There is no need to remove default mappings since once known
* default mappings should be preserved. Double-insertion in case
* mapping are re-added at a later point in time is taken care of.
*/
}

View File

@ -132,12 +132,8 @@ void Session_component::update_io_mmu_devices()
if (used_by_owned_device)
return;
dev.for_each_io_mmu(
[&] (Device::Io_mmu const & io_mmu) {
if (io_mmu.name == io_mmu_dev.name())
used_by_owned_device = true;
},
[&] () { });
dev.with_optional_io_mmu(io_mmu_dev.name(), [&] () {
used_by_owned_device = true; });
});
/* synchronise with IOMMU domains */