Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEX: Allocate a VMA allocator when running on a 48-bit VA #4299

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

Sonicadvance1
Copy link
Member

When running on a system with a 48-bit VA, if FEX does any allocations between us reserving the upper 128TB and the application running, then /technically/ we are intersecting with the application's memory region in the lower 47-bits.

This didn't typically result in any problems due to how ASLR works, but if we did any large allocations (like #4291 wants with 128MB VMA region) then these typically get pushed higher in the VA space.

Again not usually a problem, but if you happen to be running an application that is using MAP_FIXED with hardcoded addresses then this can stomp over FEX-Emu memory causing problems.

This is what happens with Wine, it reserves the upper-32MB of its 47-bit VA space, which is /highly/ likely to stomp on FEX memory. In-fact it likely occurs all the time, we just got lucky with whatever it was clobbering wasn't used at the time.

On 39-bit VA systems this isn't a problem because the mmap fails outright with a warning message from WINE.

Because we are already reserving the upper 128TB of VA space, instead just always enable our allocator and use the regions that were reserved. We need to be a little bit careful to ensure we don't accidentally allocate more memory post-reservation but that just requires a small adjustment to our unique_ptr and constructor for the 64BitAllocator.

This means /all/ FEX-Emu allocations will be in the upper 128TB VA space when running 64-bit applications on a 48-bit VA system. Which is kind of nice.

Fixes WINE in #4291 when the allocator stats are bumped to 128MB per process.

@Sonicadvance1 Sonicadvance1 force-pushed the fix_48bit_wine branch 2 times, most recently from 9ba206a to 8c349d4 Compare January 24, 2025 01:12
@Sonicadvance1
Copy link
Member Author

Had to do a tertiary bug fix in our Allocator that we hadn't hit before. This never occurred on the 32-bit side where we reserve the upper 32-bits because the first VMA region would be hundreds of gigabytes. Since we're using the regions in the top 128TB on 48-bit systems now, due to how ASLR is laid out (roughly starts in the middle of the VA) there was a pretty high chance of the /first/ VMA region being small enough to hit the bug.

@Sonicadvance1 Sonicadvance1 force-pushed the fix_48bit_wine branch 2 times, most recently from 668a702 to fab8506 Compare January 24, 2025 03:32
When running on a system with a 48-bit VA, if FEX does any allocations
between us reserving the upper 128TB and the application running, then
/technically/ we are intersecting with the application's memory region
in the lower 47-bits.

This didn't typically result in any problems due to how ASLR works, but
if we did any large allocations (like FEX-Emu#4291 wants with 128MB VMA region)
then these typically get pushed higher in the VA space.

Again not usually a problem, but if you happen to be running an
application that is using MAP_FIXED with hardcoded addresses then this
can stomp over FEX-Emu memory causing problems.

This is what happens with Wine, it reserves the upper-32MB of its 47-bit
VA space, which is /highly/ likely to stomp on FEX memory. In-fact it
likely occurs all the time, we just got lucky with whatever it was
clobbering wasn't used at the time.

On 39-bit VA systems this isn't a problem because the mmap fails
outright with a warning message from WINE.

Because we are already reserving the upper 128TB of VA space, instead
just always enable our allocator and use the regions that were reserved.
We need to be a little bit careful to ensure we don't accidentally
allocate more memory post-reservation but that just requires a small
adjustment to our unique_ptr and constructor for the 64BitAllocator.

This means /all/ FEX-Emu allocations will be in the upper 128TB VA space
when running 64-bit applications on a 48-bit VA system. Which is kind of
nice.

Fixes WINE in FEX-Emu#4291 when the allocator stats are bumped to 128MB per
process.
@Sonicadvance1 Sonicadvance1 force-pushed the fix_48bit_wine branch 2 times, most recently from 942838e to d2036f1 Compare January 25, 2025 00:34
…gions

When small regions were being used for VMA allocations (less than 64
pages), this function was truncating the result to zero. Resulting in
incorrect `LiveVMARegion` size calculations. It would calculate that the
FlexBitSet consumes zero bits of space, even though it needs to use at
least 2, or 3 if we actually want to allocate anything from that
LiveVMARegion.

This was noticed in this PR because our VMA region tracking is being
used more, which has a more likely chance to have small VMA regions for
allocating from. Cause a 1page allocation to try and use a 3 page VMA
region for allocation, but failing because the FlexBitSet size wasn't
calculated correctly.

- Page layout:
- [0x0, 0x1000):    struct LiveVMARegion
- [0x1000, 0x2000): FlexBitSet<uint64_t> UsedPages
-  ^ This space wasn't allocated/mprotected due to the size not
   calculating correctly.
- [0x2000, 0x3000): Memory for allocation
Anything less than three pages can't be used for FEX allocations due to
VMA implementation details. Plus we may have reduced a single page
reservation to zero with the prior ObjectAlloc size reservation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant