From: Junhua Shen <Junhua.Shen@amd.com>
To: <Alexander.Deucher@amd.com>, <Felix.Kuehling@amd.com>,
<Christian.Koenig@amd.com>, <Oak.Zeng@amd.com>,
<Jenny-Jing.Liu@amd.com>, <Philip.Yang@amd.com>,
<Xiaogang.Chen@amd.com>, <Ray.Huang@amd.com>,
<honglei1.huang@amd.com>, <Lingshan.Zhu@amd.com>,
<simona@ffwll.ch>
Cc: <amd-gfx@lists.freedesktop.org>,
<dri-devel@lists.freedesktop.org>, <Junhua.Shen@amd.com>
Subject: [PATCH v5 8/8] drm/amdgpu: integrate VRAM migration into SVM restore and realign paths
Date: Fri, 5 Jun 2026 15:53:40 +0800 [thread overview]
Message-ID: <20260605075340.20199-9-Junhua.Shen@amd.com> (raw)
In-Reply-To: <20260605075340.20199-1-Junhua.Shen@amd.com>
Integrate the VRAM migration infrastructure into the SVM restore and
boundary realignment paths to ensure correct interaction between
migration and the existing SVM lifecycle framework.
Suppress restore for realigned ranges:
- Add suppress_restore flag to amdgpu_svm_range
- Set flag before svm_restore_realign_boundary() evicts a crossing range
- Prevent migration notifier from enqueueing restore work while
realignment or VRAM migration is in progress
- Remove existing restore-list entry and drop its queue kref
- On realign failure, clear flag and re-enqueue restore for rollback
- Enqueue, worker retry, and put_if_dequeued paths respect the flag
Extend svm_restore_range() with migration support:
- Move amdgpu_svm_range_is_valid() check before map_ctx setup
- Set devmem_only = false since restore should not force VRAM placement
- Add device_private_page_owner for proper devmem identification
Signed-off-by: Junhua Shen <Junhua.Shen@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c | 4 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.h | 1 +
drivers/gpu/drm/amd/amdgpu/amdgpu_userptr.c | 76 +++++++++++++++----
3 files changed, 65 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c
index 88923e6a0194..31229c4770b8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.c
@@ -728,11 +728,13 @@ amdgpu_svm_range_put_if_dequeued(struct amdgpu_svm *svm,
list_add_tail(&range->work_node, &svm->gc.list);
range->queue_state = AMDGPU_SVM_RANGE_IN_GC;
queue_gc = true;
- } else if (RESTORE_WORK(range->pending_ops)) {
+ } else if (RESTORE_WORK(range->pending_ops) &&
+ !READ_ONCE(range->suppress_restore)) {
list_add_tail(&range->work_node, &svm->restore.list);
range->queue_state = AMDGPU_SVM_RANGE_IN_RESTORE;
queue_restore = true;
} else {
+ range->pending_ops &= ~AMDGPU_SVM_RANGE_OP_RESTORE;
range->queue_state = AMDGPU_SVM_RANGE_NOT_QUEUED;
release_kref = true;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.h
index 2d677f0965b4..4bf05c304564 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_svm_range.h
@@ -55,6 +55,7 @@ struct amdgpu_svm_range {
struct drm_gpusvm_range base;
struct list_head work_node;
bool gpu_mapped;
+ bool suppress_restore;
u8 queue_state;
u8 pending_ops;
unsigned long pending_start_page;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userptr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userptr.c
index 8bf00aed7f15..45a611479d1c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userptr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userptr.c
@@ -28,6 +28,7 @@
#include "amdgpu_svm_attr.h"
#include "amdgpu.h"
#include "amdgpu_amdkfd.h"
+#include "amdgpu_migrate.h"
#include <drm/drm_exec.h>
#include <drm/drm_gpusvm.h>
@@ -151,6 +152,11 @@ svm_restore_enqueue_work(struct amdgpu_svm *svm,
spin_lock(&svm->work_lock);
+ if (!UNMAP_WORK(pending_ops) && READ_ONCE(range->suppress_restore)) {
+ spin_unlock(&svm->work_lock);
+ return;
+ }
+
/* Deny any work if range is unmapped */
if (UNMAP_WORK(range->pending_ops)) {
spin_unlock(&svm->work_lock);
@@ -232,7 +238,7 @@ svm_restore_range(struct amdgpu_svm *svm, struct amdgpu_svm_range *range)
unsigned long range_start_page;
int ret;
struct drm_gpusvm_ctx map_ctx;
- bool devmem_possible, need_vram_migration;
+ bool devmem_possible;
amdgpu_svm_assert_locked(svm);
@@ -247,20 +253,20 @@ svm_restore_range(struct amdgpu_svm *svm, struct amdgpu_svm_range *range)
if (!attr_range || !amdgpu_svm_attr_has_access(attrs.access))
return 0;
+ if (amdgpu_svm_range_is_valid(svm, range, &attrs))
+ return 0;
+
devmem_possible = amdgpu_svm_devmem_possible(svm);
- need_vram_migration = devmem_possible &&
- amdgpu_svm_attr_prefer_vram(&attrs);
map_ctx = (struct drm_gpusvm_ctx){
.read_only = !!(attrs.flags & AMDGPU_SVM_ATTR_BIT_GPU_RO),
.devmem_possible = devmem_possible,
- .devmem_only = need_vram_migration,
+ .devmem_only = false,
.check_pages_threshold = devmem_possible ? SZ_64K : 0,
+ .device_private_page_owner = devmem_possible ?
+ AMDGPU_PGMAP_OWNER(svm->adev) : NULL,
};
- if (amdgpu_svm_range_is_valid(svm, range, &attrs))
- return 0;
-
AMDGPU_SVM_RANGE_DEBUG(range, "RESTORE - GET PAGES");
ret = amdgpu_svm_range_get_pages(svm, &range->base, &map_ctx);
@@ -289,6 +295,42 @@ static bool amdgpu_svm_nonretryable(int ret)
}
}
+static void
+svm_restore_suppress_range_restore(struct amdgpu_svm *svm,
+ struct amdgpu_svm_range *range)
+{
+ bool release_kref = false;
+
+ spin_lock(&svm->work_lock);
+
+ WRITE_ONCE(range->suppress_restore, true);
+ range->pending_ops &= ~AMDGPU_SVM_RANGE_OP_RESTORE;
+
+ if (range->queue_state == AMDGPU_SVM_RANGE_IN_RESTORE) {
+ list_del_init(&range->work_node);
+ range->queue_state = AMDGPU_SVM_RANGE_NOT_QUEUED;
+ range->pending_start_page = ULONG_MAX;
+ range->pending_last_page = 0;
+ release_kref = true;
+ }
+
+ spin_unlock(&svm->work_lock);
+
+ if (release_kref)
+ drm_gpusvm_range_put(&range->base);
+}
+
+static void
+svm_restore_unsuppress_range_restore(struct amdgpu_svm *svm,
+ struct amdgpu_svm_range *range,
+ unsigned long start_page,
+ unsigned long last_page)
+{
+ WRITE_ONCE(range->suppress_restore, false);
+ svm_restore_enqueue_work(svm, range, start_page, last_page,
+ AMDGPU_SVM_RANGE_OP_RESTORE);
+}
+
static void amdgpu_svm_restore_worker(struct work_struct *w)
{
struct delayed_work *dwork = to_delayed_work(w);
@@ -334,17 +376,19 @@ static void amdgpu_svm_restore_worker(struct work_struct *w)
op_ctx.start_page,
op_ctx.last_page, ret);
spin_lock(&svm->work_lock);
- if (!UNMAP_WORK(op_ctx.range->pending_ops))
+ if (!UNMAP_WORK(op_ctx.range->pending_ops) &&
+ !READ_ONCE(op_ctx.range->suppress_restore)) {
op_ctx.range->pending_ops |=
AMDGPU_SVM_RANGE_OP_RESTORE;
- op_ctx.range->pending_start_page =
- min(op_ctx.range->pending_start_page,
- op_ctx.start_page);
- op_ctx.range->pending_last_page =
- max(op_ctx.range->pending_last_page,
- op_ctx.last_page);
+ op_ctx.range->pending_start_page =
+ min(op_ctx.range->pending_start_page,
+ op_ctx.start_page);
+ op_ctx.range->pending_last_page =
+ max(op_ctx.range->pending_last_page,
+ op_ctx.last_page);
+ need_resched = true;
+ }
spin_unlock(&svm->work_lock);
- need_resched = true;
} else {
AMDGPU_SVM_TRACE(
"restore work drop non retryable [0x%lx-0x%lx] ret=%d\n",
@@ -746,6 +790,7 @@ svm_restore_realign_boundary(struct amdgpu_svm *svm,
rs = drm_gpusvm_range_start(r) >> PAGE_SHIFT;
rl = (drm_gpusvm_range_end(r) >> PAGE_SHIFT) - 1;
+ svm_restore_suppress_range_restore(svm, svm_range);
amdgpu_svm_range_evict(svm, r);
if (svm_range->gpu_mapped) {
@@ -755,6 +800,7 @@ svm_restore_realign_boundary(struct amdgpu_svm *svm,
if (ret < 0) {
AMDGPU_SVM_TRACE("zap failed ret=%d [0x%lx-0x%lx]\n",
ret, rs, rl);
+ svm_restore_unsuppress_range_restore(svm, svm_range, rs, rl);
drm_exec_fini(&exec);
return ret;
}
--
2.34.1
prev parent reply other threads:[~2026-06-05 7:54 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-05 7:53 [PATCH v5 0/8] drm/amdgpu: SVM VRAM migration via drm_pagemap (unified XNACK on/off) Junhua Shen
2026-06-05 7:53 ` [PATCH v5 1/8] drm/amdgpu: add VRAM migration infrastructure for drm_pagemap Junhua Shen
2026-06-05 7:53 ` [PATCH v5 2/8] drm/amdgpu: implement drm_pagemap SDMA migration callbacks Junhua Shen
2026-06-05 7:53 ` [PATCH v5 3/8] drm/amdgpu: implement synchronous TTM eviction for SVM BOs Junhua Shen
2026-06-05 7:53 ` [PATCH v5 4/8] drm/amdgpu: hook up ZONE_DEVICE registration in device init and reset Junhua Shen
2026-06-05 7:53 ` [PATCH v5 5/8] drm/amdgpu: add SVM range migration helpers for drm_pagemap Junhua Shen
2026-06-05 7:53 ` [PATCH v5 6/8] drm/amdgpu: refactor SVM attr devmem_possible and prefer_vram API Junhua Shen
2026-06-05 7:53 ` [PATCH v5 7/8] drm/amdgpu: integrate VRAM migration into SVM fault and prefetch paths Junhua Shen
2026-06-05 7:53 ` Junhua Shen [this message]
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=20260605075340.20199-9-Junhua.Shen@amd.com \
--to=junhua.shen@amd.com \
--cc=Alexander.Deucher@amd.com \
--cc=Christian.Koenig@amd.com \
--cc=Felix.Kuehling@amd.com \
--cc=Jenny-Jing.Liu@amd.com \
--cc=Lingshan.Zhu@amd.com \
--cc=Oak.Zeng@amd.com \
--cc=Philip.Yang@amd.com \
--cc=Ray.Huang@amd.com \
--cc=Xiaogang.Chen@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=honglei1.huang@amd.com \
--cc=simona@ffwll.ch \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox