Skip to content

fix(rocjitsu): back caller-placed allocations at KFD map time - #10337

Closed
amd-arosa wants to merge 1 commit into
developfrom
users/arosa/rocjitsu/fix/alloc-map
Closed

amd-arosa wants to merge 1 commit into
developfrom
users/arosa/rocjitsu/fix/alloc-map

Conversation

@amd-arosa

@amd-arosa amd-arosa commented Aug 18, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

SimulatedKfd::map_memory_ioctl never backs a caller-placed allocation.

In local (non-daemon) mode alloc_memory_ioctl creates neither a memfd nor a
host mapping when the caller supplies va_addr and the allocation is not
USERPTR, so alloc.host_ptr stays null. map_memory_ioctl then gates its
backing on if (alloc.host_ptr && !alloc.user_va) and skips it, and MAP is the
last chance to back the allocation — no mmap of the KFD fd follows for device
memory.

This is the shape ROCr actually uses: it reserves the VA itself with a
PROT_NONE mmap and asks the driver to back it. Today that only appears to
work because the access falls through to passthrough.

Technical Details

At MAP time, adopt the caller's reservation the way dispatch_mmap already
adopts MAP_FIXED pages: lift the PROT_NONE with mprotect and record the
pages as caller-owned (host_ptr_owned = false) so teardown never unmaps
memory the caller owns.

Guarded to the case it is meant for — local mode only, only when there is a
user_va and no host_ptr, and never for USERPTR (which already carries the
caller's own pages) or DOORBELL (which must keep reaching the doorbell path).

If the mprotect fails, the GPU VA was never a host VA the caller reserved.
That is left unbacked and the ioctl still reports success, because such a
client previously fell through to passthrough and a failing ioctl would be a
regression for it. The case is logged through util::Logger::vm.

Changed files:

  • emulation/rocjitsu/lib/rocjitsu/src/rocjitsu/kmd/linux/simulated_kfd.cpp
  • emulation/rocjitsu/tests/kfd_ioctl_test.cpp

Scope note

An earlier revision of this PR also tagged tensor-DMA byte copies with the
issuing process id. That half is now already fixed on develop —
Wavefront::write_gpu_memory() passes process_id_ through to
memory->write_block(), and copy_dense_tensor routes through it (#9775).
This PR has been narrowed to the KFD half, which is still present.

Issue Tracking

GitHub issue: #10331

Test Plan

Written test-first: the regression tests were added and observed to fail
against develop before any source change, then the fix was applied and the
tests re-run.

Test Result

Full suite on current develop (60c29ef): 100% tests passed, 0 failed out
of 3218
.

@therock-pr-bot

therock-pr-bot Bot commented Aug 18, 2026 •

Copy link
Copy Markdown

✅ All Checks Passed — Ready for Review

Check Status Details
📝 PR Description ✅ Pass —
⛔ Forbidden Files ✅ Pass —
🧪 Unit Test ✅ Pass —
🔎 pre-commit ✅ Pass —
🚫 Draft PR 🔜 To Be Enabled —
🚩 Feature Flag 🔜 To Be Enabled —
📊 Code Coverage 🔜 To Be Enabled —
🤖 therock-pr-bot ✅ Pass —

🎉 All checks passed! This PR is ready for review.

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

🙋 Wish to Override Policy?

@amd-arosa
amd-arosa marked this pull request as draft August 18, 2026 17:23
@amd-arosa
amd-arosa force-pushed the users/arosa/rocjitsu/fix/alloc-map branch from 75e0a2f to a60cc5c Compare August 18, 2026 17:54
@therock-pr-bot

Copy link
Copy Markdown

🎉 All checks passed! This PR is ready for review.

@amd-arosa
amd-arosa force-pushed the users/arosa/rocjitsu/fix/alloc-map branch from a60cc5c to 9523a12 Compare August 18, 2026 17:57
@amd-arosa amd-arosa changed the title fix(rocjitsu): back a caller-placed allocation and tag tensor DMA fix(rocjitsu): back caller-placed allocations at KFD map time Aug 18, 2026
@amd-arosa
amd-arosa marked this pull request as ready for review August 18, 2026 17:57
@amd-arosa
amd-arosa marked this pull request as draft August 18, 2026 18:03
@amd-arosa
amd-arosa force-pushed the users/arosa/rocjitsu/fix/alloc-map branch from 9523a12 to 283f7b0 Compare August 18, 2026 18:53
MAP_MEMORY_TO_GPU only entered an allocation into the process page table
when it already had a host pointer. A caller-placed allocation never has
one: ROCr reserves the VA itself with a PROT_NONE mmap and asks the
driver to back it, and alloc_memory_ioctl deliberately creates neither a
memfd nor a host mapping for a caller-supplied va_addr in local mode. No
mmap of the KFD fd follows for device memory, so MAP was the last chance
to back the range and it did nothing: the allocation stayed absent from
the page table and accesses only "worked" by falling through to
passthrough, bypassing GPU translation entirely.

Adopt the caller's reservation in map_memory_ioctl the way dispatch_mmap
already adopts MAP_FIXED pages: mprotect the range READ|WRITE through
libc_passthrough and take it as host_ptr, left caller-owned so teardown
never unmaps pages the driver did not create. USERPTR already carries the
caller's own pages and DOORBELL must keep reaching the doorbell path, so
both are excluded, and daemon mode keeps its memfd path. The cost, noted
at the call site, is that the caller's PROT_NONE reservation becomes
host-readable for the life of the allocation, so a stray CPU dereference
of a device pointer no longer faults the way it would on hardware -- the
same trade dispatch_mmap already makes.

When the mprotect fails the range is logged and left unbacked, so a
client that passed a VA it never reserved keeps its pre-fix passthrough
behaviour instead of meeting a newly failing ioctl. errno is captured
before the logger runs, and the line goes to the cp group alongside the
other MAP_MEMORY records rather than hiding under vm.

Backing these allocations makes a latent teardown asymmetry live:
free_memory_ioctl skipped its unmap_from_gpu for any caller-placed
allocation, which was inert while such an allocation never had a host
pointer, but now strands page-table entries whenever a client FREEs
without UNMAPping first. unmap_from_gpu only drops PTEs and never
munmaps, so the guard comes off.

tests/kfd_ioctl_test.cpp gains three regressions: a PROT_NONE
reservation placed by the caller is mapped page-by-page onto the
reserved pages after MAP and is writable afterwards (this failed before
the fix, with the first page absent from the page table), FREE without a
preceding UNMAP leaves no entry behind, and a GPU-only VA that is not
mapped in the process still reports success and stays unbacked.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@amd-arosa
amd-arosa force-pushed the users/arosa/rocjitsu/fix/alloc-map branch from 283f7b0 to b308623 Compare August 18, 2026 19:53
@amd-arosa
amd-arosa marked this pull request as ready for review August 18, 2026 19:55
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been inactive for 25 days and will be marked as stale.

If you would like to keep this PR open, please:

  • Add new commits
  • Add a comment explaining why it should remain open

This PR will be automatically closed in 5 days if no further activity occurs.

@github-actions github-actions Bot added the Stale PR has no activity for 25+ days label Sep 13, 2026

@atgutier atgutier left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor issue in a test found by the agent, so approving with comment:

[MINOR] emulation/rocjitsu/tests/kfd_ioctl_test.cpp:2180 — Hard-coded GPU-only VA breaks the TSan
suite

Reasoning: The test assumes 0x0000210000000000 is absent from every process address space. TSan maps
that address, so the precondition at line 2186 fails before the KFD behavior is exercised.

Evidence: In PR CI, mincore(kGpuOnlyVa, ...) returned 0 rather than -1/ENOMEM. This was the sole
failing test in the TSan suite: KfdIoctlTest.MapMemoryToleratesCallerPlacedVaThatIsNotAHostVa.

Suggested fix: Obtain a process-specific hole dynamically—for example, create an anonymous mapping,
capture its address, unmap it, verify mincore returns ENOMEM, and immediately use that address for
the allocation—instead of relying on a fixed virtual address.

Confidence: high; confirmed directly from the TSan job log.

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically closed due to inactivity (30 days with no updates).

If you'd like to continue working on this, feel free to reopen the PR or create a new one.

@github-actions github-actions Bot closed this Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants