Skip to content

fix(agc): write-watch the AGC driver memory on Linux - #8120

Open
Raghav314 wants to merge 1 commit into
boykopovar:mainfrom
Raghav314:fix/agc-driver-memory-write-watch
Open

Raghav314 wants to merge 1 commit into
boykopovar:mainfrom
Raghav314:fix/agc-driver-memory-write-watch

Conversation

@Raghav314

Copy link
Copy Markdown
Contributor

What

#6160 maps 2 MiB of AGC driver memory at 0xfe0000000 (the FS table and its routine) and registers it as a guest allocation. On Windows it is committed inside the guest arena, which is write-watched. On Linux the address is in the arena's system-reserved hole, so it is a plain mmap outside the write watch.

Every address-based build maps the registered ranges, so it includes this range. When the host import budget refuses its import, a range normally gets a heap mirror refreshed by the blocks the CPU writes. This range is not watched, so it gets no mirror (unwatched heaps on the [buffers] line) and is copied on the CPU, all 2 MiB, on every build.

  • On Linux the driver memory is now registered with the write watch after its table is written, so a refused import is served from a mirror like any other watched range.
  • If the write watch is not available, nothing changes.

PPSA36082

Whether the import is refused depends on whether the first build that maps the range comes before the import budget fills, so it varies by run. With APS5_HOST_IMPORT_MIB=6784, APS5_PROFILE_DRAW=1, level UI standing still, about 84 s from launch, on main 1e774a3 with #5656 and #6946:

The frame rate did not change in that scene (72.2 against 71.6 fps), since the copies are not what limits it there. With the default import budget the range was imported in the runs I made, so nothing was copied before or after.

Tested

Linux (CachyOS), x86-64, GCC, 7800X3D / RTX 4090, NVIDIA 615.78.08, on main 0929be5, rebased without conflicts onto 0d8c51a, whose new commits do not touch these files.

  • agc_driver_compute_fs_table_calls also checks that the driver memory is write-watched when the write watch is available. It fails without the change ("the AGC driver memory at 0xfe0000000 is not write-watched") and passes with it.
  • The linux job of current build.yml run locally: configure with SPIRV tools on, test registration check, build, libs, the whole ctest and conventions, on main 0929be5: 1662/1662 pass, 16 expected skips, conventions OK.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none
  • GPUs tested: NVIDIA GeForce RTX 4090, 615.78.08, Linux 7.2.10 (CachyOS)
  • AI-assisted: yes

On Linux the 2 MiB AGC driver memory at 0xfe0000000 is a plain mapping in
the arena's system-reserved hole, outside the write watch, while Windows
commits it inside the write-watched arena. Every address-based build maps
the registered ranges, so when the host import budget refuses the range it
gets no heap mirror and is copied on the CPU for every build. The range is
now registered with the write watch, so a refused import is served from a
mirror refreshed by the blocks the CPU writes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 8658 core/libs/prx/libSceAgcDriver/tests/execution/ComputeFsTableCalls.cpp L22-23

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 5021 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Lifecycle.cpp
PR 5925 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Lifecycle.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Lifecycle.cpp
PR 7201 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Lifecycle.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Lifecycle.cpp

@github-actions github-actions Bot added the agc libSceAgc* label Oct 19, 2026
@DavidAmsellem

Copy link
Copy Markdown
Contributor

First AMD-on-Linux (RADV) run of this PR. Head 7372189a7 merged onto main 2fee39f1b (clean merge), built in full and compared with the same main, on the same machine.

AMD Radeon RX 7900 XT (RADV NAVI31, gfx1100), Mesa 25.2.8, Linux Mint 22.3 (Ubuntu 24.04 base), kernel 7.0.0-38, GCC 13.3, Release.

Full suite (ANYPS5_REQUIRE_VULKAN=1 ctest -j8) at 8ec57596f: 1715/1716 with this PR, against 1715/1716 on main. The one failure is the same on both, so this PR adds none: agc_driver_guest_memory_lifetime (#7784, which #7849 addresses).

Comparing the JUnit output with main: this PR adds no ctest entry, and none is skipped or removed. The test it extends, agc_driver_compute_fs_table_calls, runs and passes.

GPUs tested: AMD Radeon RX 7900 XT (RADV NAVI31, gfx1100), Mesa 25.2.8, Linux Mint 22.3 / kernel 7.0.0-38

AI-assisted: yes

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants