[RFC/POC PATCH 12/12] drm/amdgpu: wire up SVM build system and fault handler

Honglei Huang
2026-04-20T12:08:58Z

From: Honglei Huang <honghuan@amd.com>

Enable SVM compilation and integrate it into the VM subsystem:

Kconfig:
- Add CONFIG_DRM_AMDGPU_SVM option (depends on DRM_AMDGPU and
DEVICE_PRIVATE, selects DRM_GPUSVM, HMM_MIRROR, MMU_NOTIFIER)

Makefile:
- Build amdgpu_svm.o, amdgpu_svm_attr.o, amdgpu_svm_range.o when
CONFIG_DRM_AMDGPU_SVM is enabled

amdgpu_drv.c:
- Register DRM_IOCTL_AMDGPU_GEM_SVM in the ioctl table

amdgpu_vm.c:
- Initialize vm->svm = NULL in amdgpu_vm_init
- Call amdgpu_svm_init in amdgpu_vm_make_compute for compute VMs
- Call amdgpu_svm_close + amdgpu_svm_fini in amdgpu_vm_fini
- Integrate SVM fault handling in amdgpu_vm_handle_fault

Signed-off-by: Honglei Huang <honghuan@amd.com>
---
drivers/gpu/drm/amd/amdgpu/Kconfig | 11 +++++++
drivers/gpu/drm/amd/amdgpu/Makefile | 13 ++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 ++
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 40 ++++++++++++++++++++++---
4 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig
index 1acfed2f9..22f679b85 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -74,6 +74,17 @@ config DRM_AMDGPU_USERPTR
This option selects CONFIG_HMM and CONFIG_HMM_MIRROR if it
isn't already selected to enabled full userptr support.

+config DRM_AMDGPU_SVM
+ bool "Enable AMDGPU SVM support (experimental)"
+ depends on DRM_AMDGPU
+ depends on DEVICE_PRIVATE
+ select DRM_GPUSVM
+ select HMM_MIRROR
+ select MMU_NOTIFIER
+ default y
+ help
+ Experimental SVM support based on DRM GPUSVM.
+
config DRM_AMD_ISP
bool "Enable AMD Image Signal Processor IP support"
depends on DRM_AMDGPU && ACPI
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 64e7acff8..6507d9a39 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -43,6 +43,10 @@ ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \
subdir-ccflags-y += -Wno-override-init
subdir-ccflags-$(CONFIG_DRM_AMDGPU_WERROR) += -Werror

+ifneq ($(wildcard $(objtree)/drivers/gpu/drm/Module.symvers),)
+KBUILD_EXTRA_SYMBOLS += $(objtree)/drivers/gpu/drm/Module.symvers
+endif
+
amdgpu-y := amdgpu_drv.o

# add KMS driver
@@ -303,6 +307,15 @@ amdgpu-$(CONFIG_VGA_SWITCHEROO) += amdgpu_atpx_handler.o
amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o
amdgpu-$(CONFIG_HMM_MIRROR) += amdgpu_hmm.o

+# svm support
+amdgpu-$(CONFIG_DRM_AMDGPU_SVM) += amdgpu_svm.o amdgpu_svm_attr.o \
+ amdgpu_svm_range.o
+
+.PHONY: clean-svm
+clean-svm:
+ rm -f $(obj)/amdgpu_svm.o $(obj)/amdgpu_svm_attr.o $(obj)/amdgpu_svm_range.o \
+ $(obj)/.amdgpu_svm.o.cmd $(obj)/.amdgpu_svm_attr.o.cmd $(obj)/.amdgpu_svm_range.o.cmd
+
include $(FULL_AMD_PATH)/pm/Makefile

amdgpu-y += $(AMD_POWERPLAY_FILES)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 7333e1929..12b587f9c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -50,6 +50,7 @@
#include "amdgpu_ras.h"
#include "amdgpu_reset.h"
#include "amdgpu_sched.h"
+#include "amdgpu_svm.h"
#include "amdgpu_xgmi.h"
#include "amdgpu_userq.h"
#include "amdgpu_userq_fence.h"
@@ -3068,6 +3069,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
DRM_IOCTL_DEF_DRV(AMDGPU_USERQ_SIGNAL, amdgpu_userq_signal_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_USERQ_WAIT, amdgpu_userq_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_LIST_HANDLES, amdgpu_gem_list_handles_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(AMDGPU_GEM_SVM, amdgpu_gem_svm_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
};

static const struct drm_driver amdgpu_kms_driver = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 676e24fb8..f64392117 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -43,6 +43,7 @@
#include "amdgpu_xgmi.h"
#include "amdgpu_dma_buf.h"
#include "amdgpu_res_cursor.h"
+#include "amdgpu_svm.h"
#include "kfd_svm.h"

/**
@@ -2564,6 +2565,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
int r, i;

vm->va = RB_ROOT_CACHED;
+ vm->svm = NULL;
for (i = 0; i < AMDGPU_MAX_VMHUBS; i++)
vm->reserved_vmid[i] = NULL;
INIT_LIST_HEAD(&vm->evicted);
@@ -2722,6 +2724,10 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
vm->last_update = dma_fence_get_stub();
vm->is_compute_context = true;

+ r = amdgpu_svm_init(adev, vm);
+ if (r)
+ goto unreserve_bo;
+
unreserve_bo:
amdgpu_bo_unreserve(vm->root.bo);
return r;
@@ -2754,6 +2760,9 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
unsigned long flags;
int i;

+ amdgpu_svm_close(vm);
+ amdgpu_svm_fini(vm);
+
amdgpu_amdkfd_gpuvm_destroy_cb(adev, vm);

root = amdgpu_bo_ref(vm->root.bo);
@@ -2939,8 +2948,10 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
bool write_fault)
{
bool is_compute_context = false;
+ bool has_svm = false;
struct amdgpu_bo *root;
unsigned long irqflags;
+ uint64_t fault_addr = addr;
uint64_t value, flags;
struct amdgpu_vm *vm;
int r;
@@ -2950,6 +2961,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
if (vm) {
root = amdgpu_bo_ref(vm->root.bo);
is_compute_context = vm->is_compute_context;
+ has_svm = !!vm->svm;
} else {
root = NULL;
}
@@ -2960,12 +2972,30 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,

addr /= AMDGPU_GPU_PAGE_SIZE;

- if (is_compute_context && !svm_range_restore_pages(adev, pasid, vmid,
- node_id, addr, ts, write_fault)) {
- amdgpu_bo_unref(&root);
- return true;
+ pr_debug("vm_handle_fault: pasid=%u addr=0x%llx compute=%d has_svm=%d write=%d\n",
+ pasid, fault_addr, is_compute_context, has_svm, write_fault);
+
+ if (is_compute_context && has_svm) {
+ r = amdgpu_svm_handle_fault(adev, pasid, fault_addr, write_fault);
+ pr_debug("vm_handle_fault: svm_handle_fault returned %d\n", r);
+ if (!r) {
+ amdgpu_bo_unref(&root);
+ return true;
+ }
}

+ if (is_compute_context && !has_svm) {
+ r = svm_range_restore_pages(adev, pasid, vmid,
+ node_id, addr, ts, write_fault);
+ pr_debug("vm_handle_fault: kfd svm_range_restore_pages returned %d\n", r);
+ if (!r) {
+ amdgpu_bo_unref(&root);
+ return true;
+ }
+ }
+
+ pr_debug("vm_handle_fault: SVM paths exhausted, falling through to NORETRY path\n");
+
r = amdgpu_bo_reserve(root, true);
if (r)
goto error_unref;
@@ -3020,6 +3050,8 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
error_unref:
amdgpu_bo_unref(&root);

+ pr_debug("vm_handle_fault: returning false (unhandled) pasid=%u addr=0x%llx\n",
+ pasid, fault_addr);
return false;
}

--
2.34.1