[PR #181] [MERGED] core: Rework memory manager #1367

Closed
opened 2026-02-27 21:12:16 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/shadps4-emu/shadPS4/pull/181
Author: @raphaelthegreat
Created: 6/9/2024
Status: Merged
Merged: 6/10/2024
Merged by: @georgemoralis

Base: mainHead: new_memory


📝 Commits (2)

📊 Changes

10 files changed (+339 additions, -187 deletions)

View changed files

📝 src/common/error.cpp (+1 -1)
📝 src/core/address_space.cpp (+54 -91)
📝 src/core/address_space.h (+23 -6)
📝 src/core/libraries/gnmdriver/gnmdriver.cpp (+1 -10)
📝 src/core/libraries/kernel/memory_management.cpp (+15 -1)
📝 src/core/libraries/kernel/memory_management.h (+20 -0)
📝 src/core/memory.cpp (+161 -58)
📝 src/core/memory.h (+55 -18)
📝 src/core/module.cpp (+6 -2)
📝 src/main.cpp (+3 -0)

📄 Description

Previously we were only using placeholders for user memory area, this PR now changes the system to use placeholders for all ranges. This means we no longer allow Windows to decide addresses when mapping.

Turns out that games can map to certain addresses and expect to get exact mappings, even when not specifying FIXED flags, and not even in user area. A common pattern is to perform a base mapping with addr = 0 and then subsequent mappings will be offset from the returned address of the first one.

Another issue is with the tessellation ring buffers. Games can request the address from the gnmdriver and then do dmem allocation and mapping themselves. Toolkit even asserts the returned address is the same as the provided one, again without FIXED flag. This probably relies on the fact that nothing on console uses that address range, but we can't guarantee that. A simple solution for that would be to pass virtual_addr to VirtualAlloc2, however that broke in other games (I examined crashes in Dead Cells for example).

So to avoid issues, we switch everything to placeholders. This means we can map anywhere, anytime and with 16KB granularity as necessary. So for example if a game maps a 16KB region and another next ot it, it will work correctly, while normal private allocations require 64KB granularity. The only problem I faced is that windows, even with ASLR off, reserves some lower portions of system managed area. To solve this, the address space manager will re-try multiple times to reserve, each time reducing the size by 1GB. System managed area is about 31GB and in my system it can allocate 26GB, so should be okay


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/shadps4-emu/shadPS4/pull/181 **Author:** [@raphaelthegreat](https://github.com/raphaelthegreat) **Created:** 6/9/2024 **Status:** ✅ Merged **Merged:** 6/10/2024 **Merged by:** [@georgemoralis](https://github.com/georgemoralis) **Base:** `main` ← **Head:** `new_memory` --- ### 📝 Commits (2) - [`fc887bf`](https://github.com/shadps4-emu/shadPS4/commit/fc887bf3f5efbca7881f2cf1322c8ce26a9ba53b) core: Rework memory manager - [`1092b1b`](https://github.com/shadps4-emu/shadPS4/commit/1092b1bcff7dfd9fbebdf7e45dd5901f48e27989) Fix linux build ### 📊 Changes **10 files changed** (+339 additions, -187 deletions) <details> <summary>View changed files</summary> 📝 `src/common/error.cpp` (+1 -1) 📝 `src/core/address_space.cpp` (+54 -91) 📝 `src/core/address_space.h` (+23 -6) 📝 `src/core/libraries/gnmdriver/gnmdriver.cpp` (+1 -10) 📝 `src/core/libraries/kernel/memory_management.cpp` (+15 -1) 📝 `src/core/libraries/kernel/memory_management.h` (+20 -0) 📝 `src/core/memory.cpp` (+161 -58) 📝 `src/core/memory.h` (+55 -18) 📝 `src/core/module.cpp` (+6 -2) 📝 `src/main.cpp` (+3 -0) </details> ### 📄 Description Previously we were only using placeholders for user memory area, this PR now changes the system to use placeholders for all ranges. This means we no longer allow Windows to decide addresses when mapping. Turns out that games can map to certain addresses and expect to get exact mappings, even when not specifying FIXED flags, and not even in user area. A common pattern is to perform a base mapping with addr = 0 and then subsequent mappings will be offset from the returned address of the first one. Another issue is with the tessellation ring buffers. Games can request the address from the gnmdriver and then do dmem allocation and mapping themselves. Toolkit even asserts the returned address is the same as the provided one, again without FIXED flag. This probably relies on the fact that nothing on console uses that address range, but we can't guarantee that. A simple solution for that would be to pass virtual_addr to VirtualAlloc2, however that broke in other games (I examined crashes in Dead Cells for example). So to avoid issues, we switch everything to placeholders. This means we can map anywhere, anytime and with 16KB granularity as necessary. So for example if a game maps a 16KB region and another next ot it, it will work correctly, while normal private allocations require 64KB granularity. The only problem I faced is that windows, even with ASLR off, reserves some lower portions of system managed area. To solve this, the address space manager will re-try multiple times to reserve, each time reducing the size by 1GB. System managed area is about 31GB and in my system it can allocate 26GB, so should be okay --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-02-27 21:12:16 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/shadPS4#1367
No description provided.