Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/amdgpu: Add KFD VRAM limit checking

We don't want KFD processes evicting each other over VRAM usage.
Therefore prevent overcommitting VRAM among KFD applications with
a per-GPU limit. Also leave enough room for page tables on top
of the application memory usage.

Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: Eric Huang <JinHuiEric.Huang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Felix Kuehling and committed by
Alex Deucher
611736d8 5634e38c

+75 -54
+4 -3
drivers/gpu/drm/amd/amdgpu/amdgpu.h
··· 82 82 #include "amdgpu_bo_list.h" 83 83 #include "amdgpu_gem.h" 84 84 #include "amdgpu_doorbell.h" 85 + #include "amdgpu_amdkfd.h" 85 86 86 87 #define MAX_GPU_INSTANCE 16 87 88 ··· 863 862 /* GDS */ 864 863 struct amdgpu_gds gds; 865 864 865 + /* KFD */ 866 + struct amdgpu_kfd_dev kfd; 867 + 866 868 /* display related functionality */ 867 869 struct amdgpu_display_manager dm; 868 870 ··· 878 874 atomic64_t vram_pin_size; 879 875 atomic64_t visible_pin_size; 880 876 atomic64_t gart_pin_size; 881 - 882 - /* amdkfd interface */ 883 - struct kfd_dev *kfd; 884 877 885 878 /* soc15 register offset based on ip, instance and segment */ 886 879 uint32_t *reg_offset[MAX_HWIP][HWIP_MAX_INSTANCE];
+33 -19
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
··· 31 31 32 32 static const unsigned int compute_vmid_bitmap = 0xFF00; 33 33 34 + /* Total memory size in system memory and all GPU VRAM. Used to 35 + * estimate worst case amount of memory to reserve for page tables 36 + */ 37 + uint64_t amdgpu_amdkfd_total_mem_size; 38 + 34 39 int amdgpu_amdkfd_init(void) 35 40 { 41 + struct sysinfo si; 36 42 int ret; 43 + 44 + si_meminfo(&si); 45 + amdgpu_amdkfd_total_mem_size = si.totalram - si.totalhigh; 46 + amdgpu_amdkfd_total_mem_size *= si.mem_unit; 37 47 38 48 #ifdef CONFIG_HSA_AMD 39 49 ret = kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd); ··· 97 87 return; 98 88 } 99 89 100 - adev->kfd = kgd2kfd->probe((struct kgd_dev *)adev, 101 - adev->pdev, kfd2kgd); 90 + adev->kfd.dev = kgd2kfd->probe((struct kgd_dev *)adev, 91 + adev->pdev, kfd2kgd); 92 + 93 + if (adev->kfd.dev) 94 + amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size; 102 95 } 103 96 104 97 /** ··· 141 128 { 142 129 int i, n; 143 130 int last_valid_bit; 144 - if (adev->kfd) { 131 + 132 + if (adev->kfd.dev) { 145 133 struct kgd2kfd_shared_resources gpu_resources = { 146 134 .compute_vmid_bitmap = compute_vmid_bitmap, 147 135 .num_pipe_per_mec = adev->gfx.mec.num_pipe_per_mec, ··· 181 167 &gpu_resources.doorbell_start_offset); 182 168 183 169 if (adev->asic_type < CHIP_VEGA10) { 184 - kgd2kfd->device_init(adev->kfd, &gpu_resources); 170 + kgd2kfd->device_init(adev->kfd.dev, &gpu_resources); 185 171 return; 186 172 } 187 173 ··· 210 196 gpu_resources.reserved_doorbell_mask = 0x1e0; 211 197 gpu_resources.reserved_doorbell_val = 0x0e0; 212 198 213 - kgd2kfd->device_init(adev->kfd, &gpu_resources); 199 + kgd2kfd->device_init(adev->kfd.dev, &gpu_resources); 214 200 } 215 201 } 216 202 217 203 void amdgpu_amdkfd_device_fini(struct amdgpu_device *adev) 218 204 { 219 - if (adev->kfd) { 220 - kgd2kfd->device_exit(adev->kfd); 221 - adev->kfd = NULL; 205 + if (adev->kfd.dev) { 206 + kgd2kfd->device_exit(adev->kfd.dev); 207 + adev->kfd.dev = NULL; 222 208 } 223 209 } 224 210 225 211 void amdgpu_amdkfd_interrupt(struct amdgpu_device *adev, 226 212 const void *ih_ring_entry) 227 213 { 228 - if (adev->kfd) 229 - kgd2kfd->interrupt(adev->kfd, ih_ring_entry); 214 + if (adev->kfd.dev) 215 + kgd2kfd->interrupt(adev->kfd.dev, ih_ring_entry); 230 216 } 231 217 232 218 void amdgpu_amdkfd_suspend(struct amdgpu_device *adev) 233 219 { 234 - if (adev->kfd) 235 - kgd2kfd->suspend(adev->kfd); 220 + if (adev->kfd.dev) 221 + kgd2kfd->suspend(adev->kfd.dev); 236 222 } 237 223 238 224 int amdgpu_amdkfd_resume(struct amdgpu_device *adev) 239 225 { 240 226 int r = 0; 241 227 242 - if (adev->kfd) 243 - r = kgd2kfd->resume(adev->kfd); 228 + if (adev->kfd.dev) 229 + r = kgd2kfd->resume(adev->kfd.dev); 244 230 245 231 return r; 246 232 } ··· 249 235 { 250 236 int r = 0; 251 237 252 - if (adev->kfd) 253 - r = kgd2kfd->pre_reset(adev->kfd); 238 + if (adev->kfd.dev) 239 + r = kgd2kfd->pre_reset(adev->kfd.dev); 254 240 255 241 return r; 256 242 } ··· 259 245 { 260 246 int r = 0; 261 247 262 - if (adev->kfd) 263 - r = kgd2kfd->post_reset(adev->kfd); 248 + if (adev->kfd.dev) 249 + r = kgd2kfd->post_reset(adev->kfd.dev); 264 250 265 251 return r; 266 252 } ··· 512 498 513 499 bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid) 514 500 { 515 - if (adev->kfd) { 501 + if (adev->kfd.dev) { 516 502 if ((1 << vmid) & compute_vmid_bitmap) 517 503 return true; 518 504 }
+7 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
··· 34 34 #include "amdgpu_vm.h" 35 35 36 36 extern const struct kgd2kfd_calls *kgd2kfd; 37 + extern uint64_t amdgpu_amdkfd_total_mem_size; 37 38 38 39 struct amdgpu_device; 39 40 ··· 75 74 struct mm_struct *mm; 76 75 spinlock_t lock; 77 76 char timeline_name[TASK_COMM_LEN]; 77 + }; 78 + 79 + struct amdgpu_kfd_dev { 80 + struct kfd_dev *dev; 81 + uint64_t vram_used; 78 82 }; 79 83 80 84 struct amdgpu_amdkfd_fence *amdgpu_amdkfd_fence_create(u64 context, ··· 201 195 struct kfd_vm_fault_info *info); 202 196 203 197 void amdgpu_amdkfd_gpuvm_init_mem_limits(void); 204 - void amdgpu_amdkfd_unreserve_system_memory_limit(struct amdgpu_bo *bo); 198 + void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo); 205 199 206 200 #endif /* AMDGPU_AMDKFD_H_INCLUDED */
+30 -30
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
··· 110 110 (kfd_mem_limit.max_ttm_mem_limit >> 20)); 111 111 } 112 112 113 - static int amdgpu_amdkfd_reserve_system_mem_limit(struct amdgpu_device *adev, 113 + static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev, 114 114 uint64_t size, u32 domain, bool sg) 115 115 { 116 - size_t acc_size, system_mem_needed, ttm_mem_needed; 116 + size_t acc_size, system_mem_needed, ttm_mem_needed, vram_needed; 117 + uint64_t reserved_for_pt = amdgpu_amdkfd_total_mem_size >> 9; 117 118 int ret = 0; 118 119 119 120 acc_size = ttm_bo_dma_acc_size(&adev->mman.bdev, size, 120 121 sizeof(struct amdgpu_bo)); 121 122 122 - spin_lock(&kfd_mem_limit.mem_limit_lock); 123 - 123 + vram_needed = 0; 124 124 if (domain == AMDGPU_GEM_DOMAIN_GTT) { 125 125 /* TTM GTT memory */ 126 126 system_mem_needed = acc_size + size; ··· 133 133 /* VRAM and SG */ 134 134 system_mem_needed = acc_size; 135 135 ttm_mem_needed = acc_size; 136 + if (domain == AMDGPU_GEM_DOMAIN_VRAM) 137 + vram_needed = size; 136 138 } 137 139 140 + spin_lock(&kfd_mem_limit.mem_limit_lock); 141 + 138 142 if ((kfd_mem_limit.system_mem_used + system_mem_needed > 139 - kfd_mem_limit.max_system_mem_limit) || 140 - (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > 141 - kfd_mem_limit.max_ttm_mem_limit)) 143 + kfd_mem_limit.max_system_mem_limit) || 144 + (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > 145 + kfd_mem_limit.max_ttm_mem_limit) || 146 + (adev->kfd.vram_used + vram_needed > 147 + adev->gmc.real_vram_size - reserved_for_pt)) { 142 148 ret = -ENOMEM; 143 - else { 149 + } else { 144 150 kfd_mem_limit.system_mem_used += system_mem_needed; 145 151 kfd_mem_limit.ttm_mem_used += ttm_mem_needed; 152 + adev->kfd.vram_used += vram_needed; 146 153 } 147 154 148 155 spin_unlock(&kfd_mem_limit.mem_limit_lock); 149 156 return ret; 150 157 } 151 158 152 - static void unreserve_system_mem_limit(struct amdgpu_device *adev, 159 + static void unreserve_mem_limit(struct amdgpu_device *adev, 153 160 uint64_t size, u32 domain, bool sg) 154 161 { 155 162 size_t acc_size; ··· 174 167 } else { 175 168 kfd_mem_limit.system_mem_used -= acc_size; 176 169 kfd_mem_limit.ttm_mem_used -= acc_size; 170 + if (domain == AMDGPU_GEM_DOMAIN_VRAM) { 171 + adev->kfd.vram_used -= size; 172 + WARN_ONCE(adev->kfd.vram_used < 0, 173 + "kfd VRAM memory accounting unbalanced"); 174 + } 177 175 } 178 176 WARN_ONCE(kfd_mem_limit.system_mem_used < 0, 179 177 "kfd system memory accounting unbalanced"); ··· 188 176 spin_unlock(&kfd_mem_limit.mem_limit_lock); 189 177 } 190 178 191 - void amdgpu_amdkfd_unreserve_system_memory_limit(struct amdgpu_bo *bo) 179 + void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo) 192 180 { 193 - spin_lock(&kfd_mem_limit.mem_limit_lock); 181 + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); 182 + u32 domain = bo->preferred_domains; 183 + bool sg = (bo->preferred_domains == AMDGPU_GEM_DOMAIN_CPU); 194 184 195 185 if (bo->flags & AMDGPU_AMDKFD_USERPTR_BO) { 196 - kfd_mem_limit.system_mem_used -= 197 - (bo->tbo.acc_size + amdgpu_bo_size(bo)); 198 - kfd_mem_limit.ttm_mem_used -= bo->tbo.acc_size; 199 - } else if (bo->preferred_domains == AMDGPU_GEM_DOMAIN_GTT) { 200 - kfd_mem_limit.system_mem_used -= 201 - (bo->tbo.acc_size + amdgpu_bo_size(bo)); 202 - kfd_mem_limit.ttm_mem_used -= 203 - (bo->tbo.acc_size + amdgpu_bo_size(bo)); 204 - } else { 205 - kfd_mem_limit.system_mem_used -= bo->tbo.acc_size; 206 - kfd_mem_limit.ttm_mem_used -= bo->tbo.acc_size; 186 + domain = AMDGPU_GEM_DOMAIN_CPU; 187 + sg = false; 207 188 } 208 - WARN_ONCE(kfd_mem_limit.system_mem_used < 0, 209 - "kfd system memory accounting unbalanced"); 210 - WARN_ONCE(kfd_mem_limit.ttm_mem_used < 0, 211 - "kfd TTM memory accounting unbalanced"); 212 189 213 - spin_unlock(&kfd_mem_limit.mem_limit_lock); 190 + unreserve_mem_limit(adev, amdgpu_bo_size(bo), domain, sg); 214 191 } 215 192 216 193 ··· 1236 1235 1237 1236 amdgpu_sync_create(&(*mem)->sync); 1238 1237 1239 - ret = amdgpu_amdkfd_reserve_system_mem_limit(adev, size, 1240 - alloc_domain, false); 1238 + ret = amdgpu_amdkfd_reserve_mem_limit(adev, size, alloc_domain, false); 1241 1239 if (ret) { 1242 1240 pr_debug("Insufficient system memory\n"); 1243 1241 goto err_reserve_limit; ··· 1289 1289 /* Don't unreserve system mem limit twice */ 1290 1290 goto err_reserve_limit; 1291 1291 err_bo_create: 1292 - unreserve_system_mem_limit(adev, size, alloc_domain, false); 1292 + unreserve_mem_limit(adev, size, alloc_domain, false); 1293 1293 err_reserve_limit: 1294 1294 mutex_destroy(&(*mem)->lock); 1295 1295 kfree(*mem);
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
··· 81 81 amdgpu_bo_subtract_pin_size(bo); 82 82 83 83 if (bo->kfd_bo) 84 - amdgpu_amdkfd_unreserve_system_memory_limit(bo); 84 + amdgpu_amdkfd_unreserve_memory_limit(bo); 85 85 86 86 amdgpu_bo_kunmap(bo); 87 87