From e4704a1d393731e4401b1e6018534f1702d230fa Mon Sep 17 00:00:00 2001 From: Johannes Schlatow Date: Wed, 26 Mar 2025 15:27:57 +0100 Subject: [PATCH] platform: fix potential double insertion When a session component has multiple IOMMU domains and `add_range()` fails not on the first but on another domain, the range is not removed from the first domain. This causes double insertion on the next try. genodelabs/genode#5494 --- .../src/driver/platform/session_component.cc | 16 ++++++++++---- .../pc/src/driver/platform/pc/intel/io_mmu.cc | 21 ++++--------------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/repos/os/src/driver/platform/session_component.cc b/repos/os/src/driver/platform/session_component.cc index 21d45eeb09..ad770a4556 100644 --- a/repos/os/src/driver/platform/session_component.cc +++ b/repos/os/src/driver/platform/session_component.cc @@ -335,6 +335,7 @@ Session_component::alloc_dma_buffer(size_t const size, Cache cache) Constrained_ram_allocator & _env_ram; Heap & _heap; + Io_mmu_domain_registry & _domain_registry; bool _cleanup { true }; Ram_dataspace_capability ram_cap { }; @@ -344,19 +345,26 @@ Session_component::alloc_dma_buffer(size_t const size, Cache cache) void disarm() { _cleanup = false; } - Guard(Constrained_ram_allocator & env_ram, Heap & heap) - : _env_ram(env_ram), _heap(heap) + Guard(Constrained_ram_allocator & env_ram, + Heap & heap, + Io_mmu_domain_registry & registry) + : _env_ram(env_ram), _heap(heap), _domain_registry(registry) { } ~Guard() { - if (_cleanup && buf) + if (_cleanup && buf) { + /* make sure to remove buffer range from all domains */ + _domain_registry.for_each_domain([&] (Io_mmu::Domain & domain) { + domain.remove_range({ buf->dma_addr, buf->size }); + }); destroy(_heap, buf); + } if (_cleanup && ram_cap.valid()) _env_ram.free(ram_cap); } - } guard { _env_ram, heap() }; + } guard { _env_ram, heap(), _domain_registry }; /* * Check available quota beforehand and reflect the state back diff --git a/repos/pc/src/driver/platform/pc/intel/io_mmu.cc b/repos/pc/src/driver/platform/pc/intel/io_mmu.cc index 0335cbf98d..8ac26aed55 100644 --- a/repos/pc/src/driver/platform/pc/intel/io_mmu.cc +++ b/repos/pc/src/driver/platform/pc/intel/io_mmu.cc @@ -74,23 +74,10 @@ void Intel::Io_mmu::Domain::add_range(Range const & range, Page_flags flags { RW, NO_EXEC, USER, NO_GLOBAL, RAM, Genode::CACHED }; - auto cleanup_partial_translations = [&] () { - _translation_table.remove_translation(vaddr, size, _table_allocator, - !_intel_iommu.coherent_page_walk()); - }; - - try { - _translation_table.insert_translation(vaddr, paddr, size, flags, - _table_allocator, - !_intel_iommu.coherent_page_walk(), - _intel_iommu.supported_page_sizes()); - } catch (Out_of_ram) { - cleanup_partial_translations(); - throw; - } catch (Out_of_caps) { - cleanup_partial_translations(); - throw; - } + _translation_table.insert_translation(vaddr, paddr, size, flags, + _table_allocator, + !_intel_iommu.coherent_page_walk(), + _intel_iommu.supported_page_sizes()); if (_skip_invalidation) return;