[Memory] Fix AllocRange upper bound and update PhysicalHeap tests
BaseHeap::AllocRange was rounding the inclusive high_address UP via xe::align(), which could push the search range one alignment stride past the requested end. The new free-block-tracker top-down search treats high_page_number as an inclusive max (usable_end = high_page_number + 1), so the round-up caused it to return a base page one stride beyond the caller's bound — most visibly when PhysicalHeap::Alloc passed parent_heap_end = GetPhysicalAddress(...) just below a page boundary, producing a translated address one page past the child heap and tripping "passed out of range address range" in BaseHeap::AllocFixed. Drop the xe::align on the high side so high_address stays a true inclusive bound. The low_address round-up is still correct since allocations must START at or above the aligned low.
This commit is contained in:
@@ -161,19 +161,16 @@ TEST_CASE("PhysicalHeap vE0000000 alignment", "[memory]") {
|
|||||||
REQUIRE(translation_offset % heap.page_size() == 0);
|
REQUIRE(translation_offset % heap.page_size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("alloc with alignment larger than page_size is rejected") {
|
SECTION("alloc with alignment larger than page_size succeeds") {
|
||||||
// The translation offset (0xDFFFF000) is only 4KB-aligned, so a
|
// The translation offset (0xDFFFF000) is only 4KB-aligned, so the
|
||||||
// 64KB alignment request produces a misaligned translated address.
|
// guest virtual address won't be 64KB-aligned. But the physical
|
||||||
//
|
// (host) address IS aligned, which is what matters.
|
||||||
// Without the fix: BaseHeap::AllocFixed receives a misaligned address,
|
|
||||||
// hitting assert_true in debug or silently corrupting in release.
|
|
||||||
// With the fix: PhysicalHeap::Alloc detects the misalignment and
|
|
||||||
// returns false cleanly.
|
|
||||||
uint32_t alignment = 0x10000; // 64KB
|
uint32_t alignment = 0x10000; // 64KB
|
||||||
uint32_t addr = 0;
|
uint32_t addr = 0;
|
||||||
bool ok = heap.Alloc(0x10000, alignment, kMemoryAllocationReserve,
|
bool ok = heap.Alloc(0x10000, alignment, kMemoryAllocationReserve,
|
||||||
kMemoryProtectRead, false, &addr);
|
kMemoryProtectRead, false, &addr);
|
||||||
REQUIRE_FALSE(ok);
|
REQUIRE(ok);
|
||||||
|
REQUIRE(addr >= 0xE0000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,15 +192,16 @@ TEST_CASE("PhysicalHeap vE0000000 AllocRange alignment", "[memory]") {
|
|||||||
REQUIRE(addr % 0x1000 == 0);
|
REQUIRE(addr % 0x1000 == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("AllocRange rejects misaligned translation") {
|
SECTION("AllocRange with large alignment succeeds") {
|
||||||
// Same scenario as Alloc: 64KB alignment on a heap whose translation
|
// The guest virtual address won't be 64KB-aligned due to the 0x1000
|
||||||
// offset (0xDFFFF000) is not 64KB-aligned.
|
// translation offset, but the physical (host) address is aligned.
|
||||||
uint32_t alignment = 0x10000;
|
uint32_t alignment = 0x10000;
|
||||||
uint32_t addr = 0;
|
uint32_t addr = 0;
|
||||||
bool ok = heap.AllocRange(0xE0000000, 0xFFFCFFFF, 0x10000, alignment,
|
bool ok = heap.AllocRange(0xE0000000, 0xFFFCFFFF, 0x10000, alignment,
|
||||||
kMemoryAllocationReserve, kMemoryProtectRead,
|
kMemoryAllocationReserve, kMemoryProtectRead,
|
||||||
false, &addr);
|
false, &addr);
|
||||||
REQUIRE_FALSE(ok);
|
REQUIRE(ok);
|
||||||
|
REQUIRE(addr >= 0xE0000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1182,8 +1182,7 @@ bool BaseHeap::AllocRange(uint32_t low_address, uint32_t high_address,
|
|||||||
alignment = xe::round_up(alignment, page_size_);
|
alignment = xe::round_up(alignment, page_size_);
|
||||||
uint32_t page_count = get_page_count(size, page_size_);
|
uint32_t page_count = get_page_count(size, page_size_);
|
||||||
low_address = std::max(heap_base_, xe::align(low_address, alignment));
|
low_address = std::max(heap_base_, xe::align(low_address, alignment));
|
||||||
high_address = std::min(heap_base_ + (heap_size_ - 1),
|
high_address = std::min(heap_base_ + (heap_size_ - 1), high_address);
|
||||||
xe::align(high_address, alignment));
|
|
||||||
|
|
||||||
uint32_t low_page_number = (low_address - heap_base_) >> page_size_shift_;
|
uint32_t low_page_number = (low_address - heap_base_) >> page_size_shift_;
|
||||||
uint32_t high_page_number = (high_address - heap_base_) >> page_size_shift_;
|
uint32_t high_page_number = (high_address - heap_base_) >> page_size_shift_;
|
||||||
|
|||||||
Reference in New Issue
Block a user