mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-19 08:36:49 +00:00
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
This commit is contained in:
parent
37ec1db5ea
commit
e4704a1d39
@ -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
|
||||
|
@ -74,23 +74,10 @@ void Intel::Io_mmu::Domain<TABLE>::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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user