fix(memory): expand the HLE guest-allocation arena (#843)

Co-authored-by: Foued Attar <foued.attar@lyceeastier.com>
This commit is contained in:
frangametv
2026-08-24 18:23:43 +02:00
committed by GitHub
parent 807aad18b3
commit 600fcde637
2 changed files with 18 additions and 2 deletions
@@ -29,7 +29,13 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IGuestMemoryA
private const ulong PageSize = 0x1000; private const ulong PageSize = 0x1000;
private const ulong HostAllocationGranularity = 0x10000; private const ulong HostAllocationGranularity = 0x10000;
private const ulong GuestAllocationArenaAddress = 0x00006000_0000_0000; private const ulong GuestAllocationArenaAddress = 0x00006000_0000_0000;
private const ulong GuestAllocationArenaSize = 0x0100_0000; // Full C++ runtimes can route large numbers of HLE-backed heap allocations
// through this arena. The original 16 MiB capacity could be exhausted
// during asset setup, turning a valid allocation request into a null
// pointer that failed later in unrelated guest code. Keep enough capacity
// for those workloads. Adapted from foufouadi's allocator-exhaustion
// investigation.
private const ulong GuestAllocationArenaSize = 0x2000_0000;
private const ulong GuestAllocationArenaStartOffset = PageSize; private const ulong GuestAllocationArenaStartOffset = PageSize;
private const ulong LargeDataReserveThreshold = 0x4000_0000UL; // 1 GiB private const ulong LargeDataReserveThreshold = 0x4000_0000UL; // 1 GiB
private const ulong FullCommitRegionLimit = 4UL << 30; private const ulong FullCommitRegionLimit = 4UL << 30;
@@ -14,7 +14,7 @@ public sealed class GuestMemoryAllocatorTests
public void FreedRangesAreReusedAndCoalesced() public void FreedRangesAreReusedAndCoalesced()
{ {
using var memory = new PhysicalVirtualMemory(new FakeHostMemory()); using var memory = new PhysicalVirtualMemory(new FakeHostMemory());
const ulong usableArenaSize = 0x0100_0000 - 0x1000; const ulong usableArenaSize = 0x2000_0000 - 0x1000;
Assert.True(memory.TryAllocateGuestMemory(0x4000, 0x1000, out var first)); Assert.True(memory.TryAllocateGuestMemory(0x4000, 0x1000, out var first));
Assert.True(memory.TryAllocateGuestMemory(0x8000, 0x1000, out var second)); Assert.True(memory.TryAllocateGuestMemory(0x8000, 0x1000, out var second));
@@ -34,6 +34,16 @@ public sealed class GuestMemoryAllocatorTests
Assert.Equal(first, coalesced); Assert.Equal(first, coalesced);
} }
[Fact]
public void ArenaSupportsAllocationsBeyondLegacySixteenMiBLimit()
{
using var memory = new PhysicalVirtualMemory(new FakeHostMemory());
Assert.True(memory.TryAllocateGuestMemory(0x0100_0000, 0x1000, out var first));
Assert.True(memory.TryAllocateGuestMemory(0x0020_0000, 0x1000, out var beyondLegacyLimit));
Assert.Equal(first + 0x0100_0000, beyondLegacyLimit);
}
[Fact] [Fact]
public void SegmentProtectionIsAppliedInContiguousRuns() public void SegmentProtectionIsAppliedInContiguousRuns()
{ {