From 0aafec038d258ca0b3dcfae8b6ecb47b9bdb98c5 Mon Sep 17 00:00:00 2001 From: Johannes Schlatow Date: Mon, 10 Jun 2024 18:15:13 +0200 Subject: [PATCH] platform: pass reserved memory update to IOMMU Only add default mappings on IOMMU construction and on reserved-memory updates. Issue #5232 --- repos/os/src/driver/platform/common.h | 52 ++++++++++--------- repos/os/src/driver/platform/device.h | 9 ++++ repos/os/src/driver/platform/root.cc | 18 +++++++ .../src/driver/platform/session_component.cc | 8 +-- 4 files changed, 56 insertions(+), 31 deletions(-) diff --git a/repos/os/src/driver/platform/common.h b/repos/os/src/driver/platform/common.h index 929d2d584b..411cce8b90 100644 --- a/repos/os/src/driver/platform/common.h +++ b/repos/os/src/driver/platform/common.h @@ -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(); diff --git a/repos/os/src/driver/platform/device.h b/repos/os/src/driver/platform/device.h index 1780898e2c..873198e644 100644 --- a/repos/os/src/driver/platform/device.h +++ b/repos/os/src/driver/platform/device.h @@ -417,6 +417,15 @@ class Driver::Device : private List_model::Element empty_fn(); } + template + 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 &); diff --git a/repos/os/src/driver/platform/root.cc b/repos/os/src/driver/platform/root.cc index 03a905ff57..092566f4d7 100644 --- a/repos/os/src/driver/platform/root.cc +++ b/repos/os/src/driver/platform/root.cc @@ -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. + */ } diff --git a/repos/os/src/driver/platform/session_component.cc b/repos/os/src/driver/platform/session_component.cc index 7af77553ba..2de8cb521a 100644 --- a/repos/os/src/driver/platform/session_component.cc +++ b/repos/os/src/driver/platform/session_component.cc @@ -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 */