* [PATCH AUTOSEL 6.19-5.15] drm/amdkfd: Fix GART PTE for non-4K pagesize in svm_migrate_gart_map()
[not found] <20260214010245.3671907-1-sashal@kernel.org>
@ 2026-02-14 0:58 ` Sasha Levin
2026-02-14 0:59 ` [PATCH AUTOSEL 6.19-6.12] drm/amdkfd: Relax size checking during queue buffer get Sasha Levin
2026-02-14 0:59 ` [PATCH AUTOSEL 6.19-6.12] drm/amdkfd: Handle GPU reset and drain retry fault race Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-02-14 0:58 UTC (permalink / raw)
To: patches, stable
Cc: Donet Tom, Christian König, Philip Yang,
Ritesh Harjani (IBM), Felix Kuehling, Alex Deucher, Sasha Levin,
Felix.Kuehling, amd-gfx
From: Donet Tom <donettom@linux.ibm.com>
[ Upstream commit 6c160001661b6c4e20f5c31909c722741e14c2d8 ]
In svm_migrate_gart_map(), while migrating GART mapping, the number of
bytes copied for the GART table only accounts for CPU pages. On non-4K
systems, each CPU page can contain multiple GPU pages, and the GART
requires one 8-byte PTE per GPU page. As a result, an incorrect size was
passed to the DMA, causing only a partial update of the GART table.
Fix this function to work correctly on non-4K page-size systems by
accounting for the number of GPU pages per CPU page when calculating the
number of bytes to be copied.
Acked-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Philip Yang <Philip.Yang@amd.com>
Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: Donet Tom <donettom@linux.ibm.com>
Signed-off-by: Felix Kuehling <felix.kuehling@amd.com>
Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
This confirms the issue. At line 362, `amdgpu_gart_map` already
correctly iterates `AMDGPU_GPU_PAGES_IN_CPU_PAGE` times per CPU page
(inner loop `j`). So it generates `npages *
AMDGPU_GPU_PAGES_IN_CPU_PAGE` PTEs (each 8 bytes), totaling `npages * 8
* AMDGPU_GPU_PAGES_IN_CPU_PAGE` bytes. But the DMA copy was only copying
`npages * 8` bytes — a mismatch that results in partial GART updates on
non-4K systems.
### 3. Classification
This is a clear **bug fix** for incorrect DMA size calculation. On
non-4K page systems (common on aarch64 and POWER architectures), only a
fraction of the GART PTEs would be DMA-copied to the GPU page table,
leading to:
- **GPU page faults** when accessing unmapped entries
- **Potential data corruption** if stale GART entries point to wrong
memory
- **GPU hangs** or crashes during SVM (Shared Virtual Memory) migration
### 4. Scope and Risk Assessment
- **Lines changed**: 1 line (minimal)
- **Files changed**: 1 file
- **Risk**: Very low. On 4K page systems (x86),
`AMDGPU_GPU_PAGES_IN_CPU_PAGE` = 1, so the behavior is unchanged. The
fix only affects non-4K systems where it was broken.
- **Subsystem**: AMD KFD (Kernel Fusion Driver) — GPU compute path, used
for HPC and AI workloads on AMD GPUs
### 5. User Impact
This affects users running:
- AMD GPUs with KFD/ROCm on **aarch64 or POWER** systems (which commonly
use 64K pages)
- SVM (Shared Virtual Memory) migration operations
- Without this fix, GPU compute workloads would be broken or unreliable
on non-4K page systems
### 6. Stability Indicators
- Reviewed and acked by 3 AMD DRM maintainers/developers
- The fix is mathematically obvious — the existing `amdgpu_gart_map`
function already generates `AMDGPU_GPU_PAGES_IN_CPU_PAGE` PTEs per CPU
page, so the copy size must match
- No-op on 4K page systems, so zero risk of regression for x86
### 7. Dependency Check
The fix uses `AMDGPU_GPU_PAGES_IN_CPU_PAGE` which has been defined in
`amdgpu_gart.h` for a long time. The `svm_migrate_gart_map` function and
the surrounding code exist in all recent stable trees. No additional
dependencies needed.
### Summary
This is a textbook stable backport candidate:
- **Obviously correct**: One-line fix that aligns DMA copy size with the
actual number of PTEs generated
- **Fixes a real bug**: Partial GART table update on non-4K page systems
- **Small and contained**: Single line change in a single file
- **No new features**: Pure bug fix
- **Low risk**: No-op on 4K (x86) systems; fixes broken behavior on
non-4K systems
- **Well-reviewed**: Multiple AMD maintainer acks/reviews
**YES**
drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 6ada7b4af7c68..5086caac3fd06 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -61,7 +61,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, u64 npages,
*gart_addr = adev->gmc.gart_start;
num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
- num_bytes = npages * 8;
+ num_bytes = npages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE;
r = amdgpu_job_alloc_with_ib(adev, &adev->mman.high_pr,
AMDGPU_FENCE_OWNER_UNDEFINED,
--
2.51.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH AUTOSEL 6.19-6.12] drm/amdkfd: Relax size checking during queue buffer get
[not found] <20260214010245.3671907-1-sashal@kernel.org>
2026-02-14 0:58 ` [PATCH AUTOSEL 6.19-5.15] drm/amdkfd: Fix GART PTE for non-4K pagesize in svm_migrate_gart_map() Sasha Levin
@ 2026-02-14 0:59 ` Sasha Levin
2026-02-14 0:59 ` [PATCH AUTOSEL 6.19-6.12] drm/amdkfd: Handle GPU reset and drain retry fault race Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-02-14 0:59 UTC (permalink / raw)
To: patches, stable
Cc: Donet Tom, Christian König, Philip Yang, Felix Kuehling,
Alex Deucher, Sasha Levin, Felix.Kuehling, amd-gfx
From: Donet Tom <donettom@linux.ibm.com>
[ Upstream commit 42ea9cf2f16b7131cb7302acb3dac510968f8bdc ]
HW-supported EOP buffer sizes are 4K and 32K. On systems that do not
use 4K pages, the minimum buffer object (BO) allocation size is
PAGE_SIZE (for example, 64K). During queue buffer acquisition, the driver
currently checks the allocated BO size against the supported EOP buffer
size. Since the allocated BO is larger than the expected size, this check
fails, preventing queue creation.
Relax the strict size validation and allow PAGE_SIZE-sized BOs to be used.
Only the required 4K region of the buffer will be used as the EOP buffer
and avoids queue creation failures on non-4K page systems.
Acked-by: Christian König <christian.koenig@amd.com>
Suggested-by: Philip Yang <yangp@amd.com>
Signed-off-by: Donet Tom <donettom@linux.ibm.com>
Signed-off-by: Felix Kuehling <felix.kuehling@amd.com>
Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
The commit being analyzed fixes a bug introduced by `629568d25fea8`
("Validate queue cwsr area and eop buffer size"), which added overly
strict validation. The validation was correct for 4K-page systems but
broke non-4K-page systems. The current fix relaxes the validation to
properly handle the page-size alignment used by the memory allocator.
### Conclusion
This is a clear, small, well-reviewed bug fix that restores GPU compute
functionality on non-4K page size systems. The change is logically
correct (allowing larger-than-needed buffers and aligning to page size
boundaries), has minimal risk, and has been thoroughly reviewed by AMD
GPU subsystem maintainers. It fixes a regression introduced by a prior
validation commit.
The fix meets all stable kernel criteria: it's obviously correct, fixes
a real and severe bug (complete loss of GPU compute on affected
systems), is small in scope (4 lines, 1 file), and introduces no new
features.
**YES**
drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
index 80c4fa2b0975d..2822c90bd7be4 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
@@ -275,8 +275,8 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope
/* EOP buffer is not required for all ASICs */
if (properties->eop_ring_buffer_address) {
- if (properties->eop_ring_buffer_size != topo_dev->node_props.eop_buffer_size) {
- pr_debug("queue eop bo size 0x%x not equal to node eop buf size 0x%x\n",
+ if (properties->eop_ring_buffer_size < topo_dev->node_props.eop_buffer_size) {
+ pr_debug("queue eop bo size 0x%x is less than node eop buf size 0x%x\n",
properties->eop_ring_buffer_size,
topo_dev->node_props.eop_buffer_size);
err = -EINVAL;
@@ -284,7 +284,7 @@ int kfd_queue_acquire_buffers(struct kfd_process_device *pdd, struct queue_prope
}
err = kfd_queue_buffer_get(vm, (void *)properties->eop_ring_buffer_address,
&properties->eop_buf_bo,
- properties->eop_ring_buffer_size);
+ ALIGN(properties->eop_ring_buffer_size, PAGE_SIZE));
if (err)
goto out_err_unreserve;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH AUTOSEL 6.19-6.12] drm/amdkfd: Handle GPU reset and drain retry fault race
[not found] <20260214010245.3671907-1-sashal@kernel.org>
2026-02-14 0:58 ` [PATCH AUTOSEL 6.19-5.15] drm/amdkfd: Fix GART PTE for non-4K pagesize in svm_migrate_gart_map() Sasha Levin
2026-02-14 0:59 ` [PATCH AUTOSEL 6.19-6.12] drm/amdkfd: Relax size checking during queue buffer get Sasha Levin
@ 2026-02-14 0:59 ` Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-02-14 0:59 UTC (permalink / raw)
To: patches, stable
Cc: Philip Yang, Harish Kasiviswanathan, Alex Deucher, Sasha Levin,
Felix.Kuehling, amd-gfx
From: Philip Yang <Philip.Yang@amd.com>
[ Upstream commit 5b57c3c3f22336e8fd5edb7f0fef3c7823f8eac1 ]
Only check and drain IH1 ring if CAM is not enabled.
If GPU is under reset, don't access IH to drain retry fault.
Signed-off-by: Philip Yang <Philip.Yang@amd.com>
Reviewed-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Now I have all the information needed for a thorough analysis. Let me
compile my findings.
---
## Detailed Analysis
### 1. Commit Message Analysis
**Subject:** "drm/amdkfd: Handle GPU reset and drain retry fault race"
The commit addresses a **race condition** between GPU reset and the
drain retry fault mechanism. The message describes two specific fixes:
1. "Only check and drain IH1 ring if CAM is not enabled" - a correctness
fix for interrupt handler ring selection logic
2. "If GPU is under reset, don't access IH to drain retry fault" -
protecting against hardware access during GPU reset
Both are bug fix descriptions, not feature additions.
### 2. Code Change Analysis
The patch makes two distinct changes in `kfd_svm.c`:
#### Change A: `svm_range_drain_retry_fault()` - GPU reset protection
**Before (current code):**
```2337:2364:drivers/gpu/drm/amd/amdkfd/kfd_svm.c
static void svm_range_drain_retry_fault(struct svm_range_list *svms)
{
// ... iterates over GPUs ...
amdgpu_ih_wait_on_checkpoint_process_ts(pdd->dev->adev,
pdd->dev->adev->irq.retry_cam_enabled ?
&pdd->dev->adev->irq.ih :
&pdd->dev->adev->irq.ih1);
// ... no reset protection ...
}
```
**After (patched code):** Adds
`down_read_trylock(&pdd->dev->adev->reset_domain->sem)` before accessing
the IH hardware and `up_read(...)` after. If the trylock fails (GPU is
resetting), it `continue`s to the next GPU.
**Why this matters:** `svm_range_drain_retry_fault()` calls
`amdgpu_ih_wait_on_checkpoint_process_ts()` which calls
`amdgpu_ih_get_wptr()`. Looking at `vega20_ih_get_wptr()`, it does
`RREG32_NO_KIQ(ih_regs->ih_rb_wptr)` - a **direct hardware register
read**. During GPU reset (`amdgpu_device_lock_reset_domain` takes a
write lock on `reset_domain->sem`), the hardware is being torn down and
reinitialized. Accessing registers during this window can cause:
- **System hangs** (MMIO reads to offline hardware can hang the CPU bus)
- **Garbage data reads** leading to incorrect behavior
- **Kernel crashes** if the driver acts on invalid data
This is the **exact same pattern** used throughout the amdgpu driver -
there are **20+ existing call sites** that use
`down_read_trylock(&adev->reset_domain->sem)` to protect hardware
access. The fix follows an established, well-tested pattern.
#### Change B: `svm_range_unmap_from_cpu()` - CAM-aware IH1 check
**Before:**
```c
if (adev->irq.ih1.ring_size) {
```
**After:**
```c
if (!adev->irq.retry_cam_enabled && adev->irq.ih1.ring_size) {
```
The comment already says "Check and drain ih1 ring if cam not available"
but the code was missing the `!retry_cam_enabled` check. When CAM
(Content Addressable Memory) is enabled for retry filtering, retry
faults go through the primary IH ring (`ih`), not `ih1`. Checking `ih1`
when CAM is enabled is incorrect because:
- The timestamp from `ih1` would be stale/irrelevant
- It could cause the code to `continue` early (bypassing the `ih_soft`
check below) with an incorrect `checkpoint_ts`
- This leads to retry faults being incorrectly dropped or not dropped
when they should be
This same logic (`if (adev->irq.retry_cam_enabled) return;` before `ih1`
access) already exists in `amdgpu_gmc_filter_faults_remove()`,
confirming that the fix aligns with the intended design.
### 3. Bug Classification
- **Change A:** Race condition fix - accessing hardware registers
without reset domain protection. This is a **system hang / crash**
bug.
- **Change B:** Logic bug - checking the wrong interrupt handler ring
when CAM is enabled, leading to incorrect retry fault handling
(potential data corruption or stale page mappings).
### 4. Scope and Risk Assessment
- **Lines changed:** ~10 lines of actual logic (plus 1 include)
- **Files changed:** 1 file (`kfd_svm.c`)
- **Complexity:** Low - follows a well-established pattern (20+ examples
in the codebase)
- **Risk of regression:** Very low
- The `down_read_trylock` pattern is used everywhere in amdgpu and is
proven safe
- If trylock fails, we simply skip draining for that GPU (graceful
degradation)
- The CAM check aligns with existing logic in
`amdgpu_gmc_filter_faults_remove()`
### 5. User Impact
- **Affected users:** Anyone using AMD GPUs with KFD
(compute/ROCm/OpenCL workloads) who experiences GPU resets
- **Severity:** HIGH - GPU reset + drain retry fault = potential system
hang when register access hangs the CPU
- **Without fix:** If a GPU reset happens concurrently with
`svm_range_list_fini()` (process exit), the system could hang trying
to read hardware registers from an offline GPU
### 6. Dependencies
- Requires `amdgpu_reset.h` (available since v6.1)
- Requires `reset_domain->sem` infrastructure (available since v6.1)
- Requires `retry_cam_enabled` field (available since the CAM commit in
6.6)
- The `svm_range_drain_retry_fault()` function in its current form (with
the `retry_cam_enabled` ternary) was introduced in 6.12 (commit
`6ef29715ac06`)
- This patch applies cleanly only to trees with `6ef29715ac06` and
`96316211eb5c4` (both in 6.12+)
### 7. Stability Indicators
- **Reviewed-by:** Harish Kasiviswanathan (AMD kernel engineer)
- **Author:** Philip Yang (AMD KFD maintainer, regularly contributes SVM
retry fault fixes)
- **Signed-off-by:** Alex Deucher (AMD GPU subsystem maintainer)
- Pattern is well-established in the driver (20+ existing similar uses)
### Conclusion
This commit fixes two real bugs:
1. A **race condition** between GPU reset and IH ring access that can
cause **system hangs** - this is the critical fix
2. A **logic error** in IH ring selection when CAM is enabled that
causes incorrect retry fault handling
The fix is small (10 lines of logic), follows an extremely well-
established pattern in the amdgpu driver (20+ existing call sites use
the same `down_read_trylock` on `reset_domain->sem`), has been reviewed
by an AMD engineer, was authored by the KFD SVM subsystem expert, and
addresses a real crash/hang scenario. The risk of regression is minimal.
The fix applies to kernels 6.12+ where `6ef29715ac06` ("drm/amdkfd:
Change kfd/svm page fault drain handling") exists.
**YES**
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 79ea138897fcf..a10cf8650c92b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -33,6 +33,7 @@
#include "amdgpu_hmm.h"
#include "amdgpu.h"
#include "amdgpu_xgmi.h"
+#include "amdgpu_reset.h"
#include "kfd_priv.h"
#include "kfd_svm.h"
#include "kfd_migrate.h"
@@ -2349,6 +2350,9 @@ static void svm_range_drain_retry_fault(struct svm_range_list *svms)
pr_debug("drain retry fault gpu %d svms %p\n", i, svms);
+ if (!down_read_trylock(&pdd->dev->adev->reset_domain->sem))
+ continue;
+
amdgpu_ih_wait_on_checkpoint_process_ts(pdd->dev->adev,
pdd->dev->adev->irq.retry_cam_enabled ?
&pdd->dev->adev->irq.ih :
@@ -2358,6 +2362,7 @@ static void svm_range_drain_retry_fault(struct svm_range_list *svms)
amdgpu_ih_wait_on_checkpoint_process_ts(pdd->dev->adev,
&pdd->dev->adev->irq.ih_soft);
+ up_read(&pdd->dev->adev->reset_domain->sem);
pr_debug("drain retry fault gpu %d svms 0x%p done\n", i, svms);
}
@@ -2541,7 +2546,7 @@ svm_range_unmap_from_cpu(struct mm_struct *mm, struct svm_range *prange,
adev = pdd->dev->adev;
/* Check and drain ih1 ring if cam not available */
- if (adev->irq.ih1.ring_size) {
+ if (!adev->irq.retry_cam_enabled && adev->irq.ih1.ring_size) {
ih = &adev->irq.ih1;
checkpoint_wptr = amdgpu_ih_get_wptr(adev, ih);
if (ih->rptr != checkpoint_wptr) {
--
2.51.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-02-14 1:05 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260214010245.3671907-1-sashal@kernel.org>
2026-02-14 0:58 ` [PATCH AUTOSEL 6.19-5.15] drm/amdkfd: Fix GART PTE for non-4K pagesize in svm_migrate_gart_map() Sasha Levin
2026-02-14 0:59 ` [PATCH AUTOSEL 6.19-6.12] drm/amdkfd: Relax size checking during queue buffer get Sasha Levin
2026-02-14 0:59 ` [PATCH AUTOSEL 6.19-6.12] drm/amdkfd: Handle GPU reset and drain retry fault race Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox