[PATCH v9 15/18] drm/amdgpu: implement synchronous TTM eviction for SVM BOs
Huang Rui <[email protected]> Tue, 4 Aug 2026 17:42:41 +0800
| Newsgroups | org.freedesktop.lists.amd-gfx,org.freedesktop.lists.dri-devel |
|---|---|
| Message-ID | <[email protected]> |
From: Junhua Shen <[email protected]> Implement the TTM eviction path for SVM (Shared Virtual Memory) BOs, enabling VRAM overcommit scenarios where device-private pages must be migrated back to system memory when VRAM is full. - amdgpu_ttm.c: Add SVM BO detection in amdgpu_evict_flags() to evict directly to SYSTEM domain. Add SVM BO handling in amdgpu_bo_move() to call amdgpu_svm_bo_evict() for VRAM->SYSTEM transitions, which synchronously migrates device-private pages back to RAM via SDMA. - amdgpu_migrate.c: Add amdgpu_svm_bo_evict() and amdgpu_svm_bo_is_svm() helpers. - amdgpu_object.c: Register SVM BO destroy callback in amdgpu_bo_is_amdgpu_bo() so TTM eviction can identify and handle SVM BOs correctly. Signed-off-by: Junhua Shen <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.c | 44 +++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.h | 12 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 20 ++++++++++ 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.c index 6aeba9220ac41..26b99e3088f23 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.c @@ -64,6 +64,7 @@ #include <drm/drm_pagemap.h> #include <linux/memremap.h> #include <linux/migrate.h> +#include <linux/sched/mm.h> #include "amdgpu_migrate.h" #include "amdgpu.h" @@ -648,6 +649,49 @@ static const struct drm_pagemap_devmem_ops amdgpu_pagemap_ops = { .copy_to_ram = amdgpu_svm_copy_to_ram, }; +/** + * amdgpu_svm_bo_evict - Evict SVM BO by migrating device pages back to RAM + * @bo: The amdgpu_bo to evict (must be an amdgpu_bo_svm) + * + * Called from amdgpu_bo_move() when TTM needs to evict a SVM BO from VRAM. + * Uses drm_pagemap_evict_to_ram() to synchronously migrate all device-private + * pages back to system memory via SDMA. + * + * If the owning process is exiting, there is nothing to migrate; return -EBUSY + * so the TTM eviction LRU walk skips this BO instead of aborting the whole walk + * (which would fail the allocation that triggered the eviction). Hold an mm + * reference across the call so the framework's own dead-mm path stays + * unreachable and any -EFAULT it returns is unambiguously a real error. + * + * Return: 0 on success, negative error code on failure + */ +int amdgpu_svm_bo_evict(struct amdgpu_bo *bo) +{ + struct amdgpu_bo_svm *sbo = to_amdgpu_bo_svm(bo); + struct mm_struct *mm = sbo->devmem.mm; + int r; + + if (!mmget_not_zero(mm)) + return -EBUSY; + + r = drm_pagemap_evict_to_ram(&sbo->devmem); + + mmput_async(mm); + + return r; +} + +/** + * amdgpu_svm_bo_is_svm - Check if a TTM BO is an SVM BO + * @tbo: TTM buffer object + * + * Return: true if this is an amdgpu_bo_svm (identified by destroy callback) + */ +bool amdgpu_svm_bo_is_svm(struct ttm_buffer_object *tbo) +{ + return tbo->destroy == &amdgpu_bo_svm_destroy; +} + /* drm_pagemap_ops — top-level migration entry points */ /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.h index 56c66851f0a47..e9159e8167dd7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.h @@ -30,6 +30,8 @@ #include <linux/workqueue.h> struct amdgpu_device; +struct amdgpu_bo; +struct ttm_buffer_object; #define AMDGPU_INTERCONNECT_VRAM DRM_INTERCONNECT_DRIVER #define AMDGPU_INTERCONNECT_P2P (AMDGPU_INTERCONNECT_VRAM + 1) @@ -75,12 +77,22 @@ struct amdgpu_pagemap { #if IS_ENABLED(CONFIG_DRM_AMDGPU_SVM) int amdgpu_svm_migration_init(struct amdgpu_device *adev); +int amdgpu_svm_bo_evict(struct amdgpu_bo *bo); +bool amdgpu_svm_bo_is_svm(struct ttm_buffer_object *tbo); #else static inline int amdgpu_svm_migration_init(struct amdgpu_device *adev) { return 0; } +static inline int amdgpu_svm_bo_evict(struct amdgpu_bo *bo) +{ + return -ENODEV; +} +static inline bool amdgpu_svm_bo_is_svm(struct ttm_buffer_object *tbo) +{ + return false; +} #endif /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 4dd7c712b8c31..d6ea8737dedc5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -43,6 +43,7 @@ #include "amdgpu_vram_mgr.h" #include "amdgpu_vm.h" #include "amdgpu_dma_buf.h" +#include "amdgpu_migrate.h" /** * DOC: amdgpu_object @@ -93,7 +94,8 @@ static void amdgpu_bo_user_destroy(struct ttm_buffer_object *tbo) bool amdgpu_bo_is_amdgpu_bo(struct ttm_buffer_object *bo) { if (bo->destroy == &amdgpu_bo_destroy || - bo->destroy == &amdgpu_bo_user_destroy) + bo->destroy == &amdgpu_bo_user_destroy || + amdgpu_svm_bo_is_svm(bo)) return true; return false; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index cf78d70204941..6632abd92311b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -59,6 +59,7 @@ #include "amdgpu_hmm.h" #include "amdgpu_atomfirmware.h" #include "amdgpu_res_cursor.h" +#include "amdgpu_migrate.h" #include "bif/bif_4_1_d.h" MODULE_IMPORT_NS("DMA_BUF"); @@ -121,6 +122,15 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, return; } + /* SVM BOs must evict directly to system memory for drm_pagemap + * migration back to RAM in amdgpu_bo_move(). + */ + if (amdgpu_svm_bo_is_svm(bo)) { + amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU); + *placement = abo->placement; + return; + } + switch (bo->resource->mem_type) { case AMDGPU_PL_GDS: case AMDGPU_PL_GWS: @@ -576,6 +586,16 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; } + /* SVM BO eviction: migrate device-private pages back to RAM */ + if (amdgpu_svm_bo_is_svm(bo) && + old_mem->mem_type == TTM_PL_VRAM && + new_mem->mem_type == TTM_PL_SYSTEM) { + r = amdgpu_svm_bo_evict(abo); + if (!r) + ttm_bo_move_null(bo, new_mem); + return r; + } + if (adev->mman.buffer_funcs_enabled && ((old_mem->mem_type == TTM_PL_SYSTEM && new_mem->mem_type == TTM_PL_VRAM) || -- 2.53.0