From 0a8d6ddba9ac18f3aa24d4fd5ab5b7ce6f93f167 Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Fri, 4 Nov 2022 08:10:20 +0100 Subject: [PATCH] core: Ignore constraints on allocations if allocator is exhausted Try to allocate within constraint area first. In case the area is exhausted, try allocation at other memory locations. The motivation for this is to limit DMA allocations to 4GB (since some devices require addresses below 4GB). On some platforms there is little physical RAM in this area (<1GB) and the constrainted area exhausts. In case an IOMMU is present, RAM at higher locations can still be mapped below 4GB, which is done in the platform drivers. issue #4665 --- repos/base/src/core/ram_dataspace_factory.cc | 26 +++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/repos/base/src/core/ram_dataspace_factory.cc b/repos/base/src/core/ram_dataspace_factory.cc index 04911289a0..691b9f1b6a 100644 --- a/repos/base/src/core/ram_dataspace_factory.cc +++ b/repos/base/src/core/ram_dataspace_factory.cc @@ -40,16 +40,24 @@ Ram_dataspace_factory::try_alloc(size_t ds_size, Cache cache) */ Range_allocator::Alloc_result allocated_range = Allocator::Alloc_error::DENIED; - /* - * If no physical constraint exists, try to allocate physical memory at - * high locations (3G for 32-bit / 4G for 64-bit platforms) in order to - * preserve lower physical regions for device drivers, which may have DMA - * constraints. - */ - if (_phys_range.start == 0 && _phys_range.end == ~0UL) { + /* apply constraints */ + if (_phys_range.start != 0 || _phys_range.end != ~0UL) { + for (size_t align_log2 = log2(ds_size); align_log2 >= 12; align_log2--) { + allocated_range = _phys_alloc.alloc_aligned(ds_size, (unsigned)align_log2, _phys_range); + if (allocated_range.ok()) + break; + } + } + /* + * If no physical constraint exists or constraints failed, try to allocate + * physical memory at high locations (3G for 32-bit / 4G for 64-bit platforms) + * in order to preserve lower physical regions for device drivers, which may + * have DMA constraints. + */ + if (!allocated_range.ok()) { addr_t const high_start = (sizeof(void *) == 4 ? 3UL : 4UL) << 30; - Phys_range const range { .start = high_start, .end = _phys_range.end }; + Phys_range const range { .start = high_start, .end = ~0UL }; for (size_t align_log2 = log2(ds_size); align_log2 >= 12; align_log2--) { allocated_range = _phys_alloc.alloc_aligned(ds_size, (unsigned)align_log2, range); @@ -58,7 +66,7 @@ Ram_dataspace_factory::try_alloc(size_t ds_size, Cache cache) } } - /* apply constraints, or retry if larger memory allocation failed */ + /* retry if larger non-constrained memory allocation failed */ if (!allocated_range.ok()) { for (size_t align_log2 = log2(ds_size); align_log2 >= 12; align_log2--) { allocated_range = _phys_alloc.alloc_aligned(ds_size, (unsigned)align_log2, _phys_range);