From: Matthew Krebs <matthewkrebs8@gmail.com>
To: amd-gfx@lists.freedesktop.org
Cc: Felix.Kuehling@amd.com, alexander.deucher@amd.com,
christian.koenig@amd.com, dri-devel@lists.freedesktop.org,
linux-kernel@vger.kernel.org,
Matthew Krebs <matthewkrebs8@gmail.com>,
stable@vger.kernel.org
Subject: [PATCH] drm/amdkfd: Only take the VRAM path for KFD device pages in svm_range_dma_map_dev
Date: Sat, 31 Oct 2026 21:25:00 -0400 [thread overview]
Message-ID: <20261101012500.7048-1-matthewkrebs8@gmail.com> (raw)
svm_range_dma_map_dev() treats every ZONE_DEVICE page returned by
hmm_range_fault() as VRAM of the range's SVM BO. KFD's own VRAM pages
are MEMORY_DEVICE_PRIVATE or MEMORY_DEVICE_COHERENT, but fsdax
(MEMORY_DEVICE_FS_DAX) and device-dax (MEMORY_DEVICE_GENERIC) pages are
ZONE_DEVICE too. They are system memory.
When a process maps a file on a filesystem mounted with -o dax and lets
the GPU access it (for example hipMemcpy() from the mapping, which
registers the range through the SVM ioctl), the range is in system
memory and prange->svm_bo is NULL, so the VRAM branch dereferences it:
BUG: kernel NULL pointer dereference, address: 0000000000000078
RIP: 0010:svm_range_dma_map_dev+0x13b/0x300 [amdgpu]
Call Trace:
svm_range_validate_and_map+0x600/0xa70 [amdgpu]
svm_range_set_attr+0x450/0x8c0 [amdgpu]
svm_ioctl+0x62/0x80 [amdgpu]
kfd_ioctl_svm+0x5e/0xe0 [amdgpu]
kfd_ioctl+0x532/0x680 [amdgpu]
The process is then left unkillable and later KFD calls in other
processes can block, until a reboot.
Even with an SVM BO the computed address would be wrong for such a
page. Take the VRAM path only for device private and device coherent
pages and DMA map every other page, as for normal system memory.
Fixes: 1d5dbfe6c06a ("drm/amdkfd: classify and map mixed svm range pages in GPU")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Matthew Krebs <matthewkrebs8@gmail.com>
---
Notes:
Reproducer (needs a filesystem mounted with -o dax; an emulated pmem
from memmap=4G!12G and "ndctl create-namespace -m fsdax" works too):
fd = open("/mnt/pmem/file", O_RDONLY); /* >= 64 MiB, on DAX */
src = mmap(NULL, 64 << 20, PROT_READ, MAP_SHARED, fd, 0);
hipMalloc(&dst, 64 << 20);
hipMemcpy(dst, src, 64 << 20, hipMemcpyHostToDevice);
An application doing this (hipMemcpy from an mmap of a file on the DAX
mount) oopsed as in the commit message. The minimal program above was
written afterwards and has only been run on the patched kernel.
Tested on Ubuntu 7.0.0-38-generic (based on v7.0.14) with this patch
applied to that tree (it applies cleanly), 2x Radeon Pro V620 (Navi 21,
gfx1030), ROCm 7.14, Intel Optane in fsdax mode, XFS mounted dax=always:
- Before: the application oopsed in svm_range_dma_map_dev on every
start (3 of 3, on GPU 0 and on GPU 1); the task was left unkillable
and a later hipHostRegister in another process blocked in
__synchronize_srcu until a reboot.
- After: hipMemcpy and hipHostRegister + copy from the DAX mapping,
64 MiB and 1 GiB, on both GPUs, data read back equal; the same on a
non-DAX file; the application (an LLM server mapping a 111 GB model
file from the DAX mount) starts and answers requests. No oops.
- With dynamic debug on svm_range_dma_map_dev, the pages DMA mapped
during the copy have pfns inside the pmem region, and KFD's own VRAM
pages in the same call still take the VRAM branch.
Not tested: MEMORY_DEVICE_COHERENT systems (the GPU memory registered
as coherent), device-dax (/dev/daxX.Y) mappings, other ASICs.
A stricter test would be "the page belongs to a KFD pgmap", e.g.
page_pgmap(page)->ops == &svm_migrate_pgmap_ops, which also rules out
another driver's device-coherent pages. I used the type test because it
needs no new helper; happy to switch if you prefer that.
drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index ed5e33188..354184829 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -180,7 +180,12 @@ svm_range_dma_map_dev(struct amdgpu_device *adev, struct svm_range *prange,
dma_unmap_page(dev, addr[i], PAGE_SIZE, dir);
page = hmm_pfn_to_page(hmm_pfns[i]);
- if (is_zone_device_page(page)) {
+ /*
+ * Only KFD's own VRAM pages (device private or device coherent)
+ * take the VRAM path. Other ZONE_DEVICE pages, such as fsdax or
+ * device-dax memory, are system memory and are DMA mapped below.
+ */
+ if (is_device_private_page(page) || is_device_coherent_page(page)) {
struct amdgpu_device *bo_adev = prange->svm_bo->node->adev;
addr[i] = (hmm_pfns[i] << PAGE_SHIFT) +
--
2.43.0
next reply other threads:[~2026-11-01 12:01 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-01 1:25 Matthew Krebs [this message]
2026-11-01 1:42 ` [PATCH] drm/amdkfd: Only take the VRAM path for KFD device pages in svm_range_dma_map_dev sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261101012500.7048-1-matthewkrebs8@gmail.com \
--to=matthewkrebs8@gmail.com \
--cc=Felix.Kuehling@amd.com \
--cc=alexander.deucher@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=christian.koenig@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.