Repository navigation
fix(agc): address-based builds map only memory mapped for the GPU - #1905
Merged
adriadam10 merged 1 commit intoOct 10, 2026
Merged
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
An address-based build put every readable registered range in its BDA table and imported or mirrored it, including memory the guest mapped for the CPU only. On the console a mapping reaches the GPU only if its protection has GPU access (
0x10read,0x20write).sceKernelMapDirectMemory, flexible maps, fixed remaps andsceKernelMprotect. Reservations and the main image have none; a title's mprotect with GPU bits gives the image pieces access.GuestAllocations::Mutation::AddandProtecttake the flag.Sources:
src/core/memory.hMemoryProt(CpuRead = 1,CpuWrite = 2,GpuRead = 16,GpuWrite = 32).src/kernel/memory.cppCountPageTableEntries(bool gpu)counts a range for the GPU only if its protection hasPROT_GPU_READorPROT_GPU_WRITE, andsceKernelGetPageTableStatsreports the CPU and GPU counts separately.3and sets the GPU bits where the GPU reads: its bundledlibc.prxmaps the malloc heap withsceKernelMapNamedFlexibleMemoryInternal(4h6F1LLbTiw), protection3, at both call sites (+0xb2eb,+0xb4fd); its executable's segments carry only R/W/X flags, and it mprotects the two pieces the GPU reads with0x12and0x11.PPSA36082
During loading and the main menu it registers: the 1 GiB malloc heap at
0x200000000with3, 6784 MiB of direct memory with GPU read and write, and the two 32 KiB image pieces. Its first address-based draw runs on the queue the loader's fence waits on. That draw imported the heap; the import fails to pin (the kernel logsCannot map memory with base addr 0x200000000 and size of 0x40000 pages), the fence is late, and the 512 MiB upload pool overflows (eboot0x28fba9). With this change the heap is not in the table and nothing fails to pin.In my local build I bypassed both problems by hand: a driver option,
APS5_GPU_EXCLUDE=0x200000000+0x40000000, kept that address range out of address-based builds, and a patched executable got through loading with a 2.5 GiB upload pool instead of 512 MiB. Both are specific to this title. This change replaces the first: the title maps its heap with3, which has no GPU access, so address-based builds leave it out without an option. Loading with the original 512 MiB pool also needs the changes below.It also needs #861, #1367, #1249, #290 and a follow-up I will open after this one, which imports GPU-mapped memory when it is mapped and depends on this PR. With those, on main df16c4c with an earlier version of the follow-up, 40 s runs to the main menu: 4/5 pass with this change (the other overflowed at 4.1 s; the pool's margin is thin and that is separate work), 0/3 without it (each overflowed at 503 MiB with the pin failure above).
Local changes not in this PR
I also have these on local branches. They finish making the GPU follow the guest's protection, but I am not opening them because no title I can run needs them. Do you want PRs for them?
libc.prxmaps its heap with3. PPSA36082's only range where CPU and GPU write differ (an image piece mprotected with0x12) gets no GPU stores, and it allocates nothing through AnyPS5's libc heap.WRITE_DATA,DMA_DATA, labels, waits, fills), render targets, index and vertex inputs, DCC keys, display buffers and shader code fault on such memory; texture reads see zeros. The driver's GDS backing and AvPlayer's fallback frames are mapped with GPU access. A counted PPSA36082 run made no access to memory without GPU access.0x10,0x30) reach address-based builds, and AMM PRT pages with no physical memory read zero and drop GPU stores, through an unbound Vulkan sparse buffer (strict residency). Sources: amdgpuAMDGPU_PTE_PRT, which turns off faults on unmapped PRT accesses (gmc_v8_0_set_prt), and RADV reportingsparseResidencyNonResidentStrict. PPSA36082 makes no such mappings and imports nosceAmpr*function.Tested
Linux (CachyOS), x86-64, GCC, 7800X3D / RTX 4090.
guest_memory: a direct map with3has no GPU access,0x32has;sceKernelMprotectto0x13adds it and back to3removes it; flexible maps with3and0x33likewise; the main image has none. Mapping with the GPU bits ignored fails it, and so does registering the image with GPU access.agc_driver_graphics: an address-based build includes a range with GPU access and leaves out one without. Dropping the check fails it.agc_driver_graphicsandagc_driver_flat_storepass;guest_memorypasses the new checks, then stops atCheckMlock(the working-set query), as it does without this change.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)