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 | 28 +++++++++++++++++++++ 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, 63 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.c index 54253d4dcc8d..ff45489c458e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.c @@ -628,6 +628,34 @@ 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. + * + * 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); + + return drm_pagemap_evict_to_ram(&sbo->devmem); +} + +/** + * 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 75796983f6a5..63da96c17e27 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_migrate.h @@ -29,6 +29,8 @@ #include <linux/memremap.h> struct amdgpu_device; +struct amdgpu_bo; +struct ttm_buffer_object; /* * AMDGPU_INTERCONNECT_VRAM - Protocol identifier for local VRAM access. @@ -78,12 +80,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 1fb956400696..78a677ff32bf 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 714fd8d12ca5..5a45a29ef051 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"); @@ -118,6 +119,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: @@ -568,6 +578,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.34.1
