diff options
author | Christian König <christian.koenig@amd.com> | 2018-01-25 12:36:15 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-02-19 14:18:55 -0500 |
commit | 4584312d387f758534a51d7dd0a8c0f3b23ccc6e (patch) | |
tree | 0db511c7e473a3175e0cb71e6df1d9e654f91a94 /drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |
parent | 44e1baeb6321fb4ce1dbc50c4cb895b671b2fbf9 (diff) |
drm/amdgpu: fill only the lower range with ATS entries v2
At least on x86-64 the upper range is purely used by the kernel,
avoid creating any ATS mappings there as security precaution and to
allow proper page fault reporting in the upper range.
v2: remove unused variable
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 82 |
1 files changed, 53 insertions, 29 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index e584c203c357..61cf93867b8e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -267,24 +267,33 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm) | |||
267 | * Root PD needs to be reserved when calling this. | 267 | * Root PD needs to be reserved when calling this. |
268 | */ | 268 | */ |
269 | static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, | 269 | static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, |
270 | struct amdgpu_vm *vm, | 270 | struct amdgpu_vm *vm, struct amdgpu_bo *bo, |
271 | struct amdgpu_bo *bo, | 271 | unsigned level, bool pte_support_ats) |
272 | unsigned level) | ||
273 | { | 272 | { |
274 | struct ttm_operation_ctx ctx = { true, false }; | 273 | struct ttm_operation_ctx ctx = { true, false }; |
275 | struct dma_fence *fence = NULL; | 274 | struct dma_fence *fence = NULL; |
276 | uint64_t addr, init_value; | 275 | unsigned entries, ats_entries; |
277 | struct amdgpu_ring *ring; | 276 | struct amdgpu_ring *ring; |
278 | struct amdgpu_job *job; | 277 | struct amdgpu_job *job; |
279 | unsigned entries; | 278 | uint64_t addr; |
280 | int r; | 279 | int r; |
281 | 280 | ||
282 | if (vm->pte_support_ats) { | 281 | addr = amdgpu_bo_gpu_offset(bo); |
283 | init_value = AMDGPU_PTE_DEFAULT_ATC; | 282 | entries = amdgpu_bo_size(bo) / 8; |
284 | if (level != AMDGPU_VM_PTB) | 283 | |
285 | init_value |= AMDGPU_PDE_PTE; | 284 | if (pte_support_ats) { |
285 | if (level == adev->vm_manager.root_level) { | ||
286 | ats_entries = amdgpu_vm_level_shift(adev, level); | ||
287 | ats_entries += AMDGPU_GPU_PAGE_SHIFT; | ||
288 | ats_entries = AMDGPU_VA_HOLE_START >> ats_entries; | ||
289 | ats_entries = min(ats_entries, entries); | ||
290 | entries -= ats_entries; | ||
291 | } else { | ||
292 | ats_entries = entries; | ||
293 | entries = 0; | ||
294 | } | ||
286 | } else { | 295 | } else { |
287 | init_value = 0; | 296 | ats_entries = 0; |
288 | } | 297 | } |
289 | 298 | ||
290 | ring = container_of(vm->entity.sched, struct amdgpu_ring, sched); | 299 | ring = container_of(vm->entity.sched, struct amdgpu_ring, sched); |
@@ -297,15 +306,26 @@ static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, | |||
297 | if (r) | 306 | if (r) |
298 | goto error; | 307 | goto error; |
299 | 308 | ||
300 | addr = amdgpu_bo_gpu_offset(bo); | ||
301 | entries = amdgpu_bo_size(bo) / 8; | ||
302 | |||
303 | r = amdgpu_job_alloc_with_ib(adev, 64, &job); | 309 | r = amdgpu_job_alloc_with_ib(adev, 64, &job); |
304 | if (r) | 310 | if (r) |
305 | goto error; | 311 | goto error; |
306 | 312 | ||
307 | amdgpu_vm_set_pte_pde(adev, &job->ibs[0], addr, 0, | 313 | if (ats_entries) { |
308 | entries, 0, init_value); | 314 | uint64_t ats_value; |
315 | |||
316 | ats_value = AMDGPU_PTE_DEFAULT_ATC; | ||
317 | if (level != AMDGPU_VM_PTB) | ||
318 | ats_value |= AMDGPU_PDE_PTE; | ||
319 | |||
320 | amdgpu_vm_set_pte_pde(adev, &job->ibs[0], addr, 0, | ||
321 | ats_entries, 0, ats_value); | ||
322 | addr += ats_entries * 8; | ||
323 | } | ||
324 | |||
325 | if (entries) | ||
326 | amdgpu_vm_set_pte_pde(adev, &job->ibs[0], addr, 0, | ||
327 | entries, 0, 0); | ||
328 | |||
309 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); | 329 | amdgpu_ring_pad_ib(ring, &job->ibs[0]); |
310 | 330 | ||
311 | WARN_ON(job->ibs[0].length_dw > 64); | 331 | WARN_ON(job->ibs[0].length_dw > 64); |
@@ -339,7 +359,7 @@ static int amdgpu_vm_alloc_levels(struct amdgpu_device *adev, | |||
339 | struct amdgpu_vm *vm, | 359 | struct amdgpu_vm *vm, |
340 | struct amdgpu_vm_pt *parent, | 360 | struct amdgpu_vm_pt *parent, |
341 | uint64_t saddr, uint64_t eaddr, | 361 | uint64_t saddr, uint64_t eaddr, |
342 | unsigned level) | 362 | unsigned level, bool ats) |
343 | { | 363 | { |
344 | unsigned shift = amdgpu_vm_level_shift(adev, level); | 364 | unsigned shift = amdgpu_vm_level_shift(adev, level); |
345 | unsigned pt_idx, from, to; | 365 | unsigned pt_idx, from, to; |
@@ -389,7 +409,7 @@ static int amdgpu_vm_alloc_levels(struct amdgpu_device *adev, | |||
389 | if (r) | 409 | if (r) |
390 | return r; | 410 | return r; |
391 | 411 | ||
392 | r = amdgpu_vm_clear_bo(adev, vm, pt, level); | 412 | r = amdgpu_vm_clear_bo(adev, vm, pt, level, ats); |
393 | if (r) { | 413 | if (r) { |
394 | amdgpu_bo_unref(&pt); | 414 | amdgpu_bo_unref(&pt); |
395 | return r; | 415 | return r; |
@@ -421,7 +441,7 @@ static int amdgpu_vm_alloc_levels(struct amdgpu_device *adev, | |||
421 | uint64_t sub_eaddr = (pt_idx == to) ? eaddr : | 441 | uint64_t sub_eaddr = (pt_idx == to) ? eaddr : |
422 | ((1 << shift) - 1); | 442 | ((1 << shift) - 1); |
423 | r = amdgpu_vm_alloc_levels(adev, vm, entry, sub_saddr, | 443 | r = amdgpu_vm_alloc_levels(adev, vm, entry, sub_saddr, |
424 | sub_eaddr, level); | 444 | sub_eaddr, level, ats); |
425 | if (r) | 445 | if (r) |
426 | return r; | 446 | return r; |
427 | } | 447 | } |
@@ -444,26 +464,29 @@ int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, | |||
444 | struct amdgpu_vm *vm, | 464 | struct amdgpu_vm *vm, |
445 | uint64_t saddr, uint64_t size) | 465 | uint64_t saddr, uint64_t size) |
446 | { | 466 | { |
447 | uint64_t last_pfn; | ||
448 | uint64_t eaddr; | 467 | uint64_t eaddr; |
468 | bool ats = false; | ||
449 | 469 | ||
450 | /* validate the parameters */ | 470 | /* validate the parameters */ |
451 | if (saddr & AMDGPU_GPU_PAGE_MASK || size & AMDGPU_GPU_PAGE_MASK) | 471 | if (saddr & AMDGPU_GPU_PAGE_MASK || size & AMDGPU_GPU_PAGE_MASK) |
452 | return -EINVAL; | 472 | return -EINVAL; |
453 | 473 | ||
454 | eaddr = saddr + size - 1; | 474 | eaddr = saddr + size - 1; |
455 | last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE; | 475 | |
456 | if (last_pfn >= adev->vm_manager.max_pfn) { | 476 | if (vm->pte_support_ats) |
457 | dev_err(adev->dev, "va above limit (0x%08llX >= 0x%08llX)\n", | 477 | ats = saddr < AMDGPU_VA_HOLE_START; |
458 | last_pfn, adev->vm_manager.max_pfn); | ||
459 | return -EINVAL; | ||
460 | } | ||
461 | 478 | ||
462 | saddr /= AMDGPU_GPU_PAGE_SIZE; | 479 | saddr /= AMDGPU_GPU_PAGE_SIZE; |
463 | eaddr /= AMDGPU_GPU_PAGE_SIZE; | 480 | eaddr /= AMDGPU_GPU_PAGE_SIZE; |
464 | 481 | ||
482 | if (eaddr >= adev->vm_manager.max_pfn) { | ||
483 | dev_err(adev->dev, "va above limit (0x%08llX >= 0x%08llX)\n", | ||
484 | eaddr, adev->vm_manager.max_pfn); | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | |||
465 | return amdgpu_vm_alloc_levels(adev, vm, &vm->root, saddr, eaddr, | 488 | return amdgpu_vm_alloc_levels(adev, vm, &vm->root, saddr, eaddr, |
466 | adev->vm_manager.root_level); | 489 | adev->vm_manager.root_level, ats); |
467 | } | 490 | } |
468 | 491 | ||
469 | /** | 492 | /** |
@@ -1660,16 +1683,16 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, | |||
1660 | struct dma_fence **fence) | 1683 | struct dma_fence **fence) |
1661 | { | 1684 | { |
1662 | struct amdgpu_bo_va_mapping *mapping; | 1685 | struct amdgpu_bo_va_mapping *mapping; |
1686 | uint64_t init_pte_value = 0; | ||
1663 | struct dma_fence *f = NULL; | 1687 | struct dma_fence *f = NULL; |
1664 | int r; | 1688 | int r; |
1665 | uint64_t init_pte_value = 0; | ||
1666 | 1689 | ||
1667 | while (!list_empty(&vm->freed)) { | 1690 | while (!list_empty(&vm->freed)) { |
1668 | mapping = list_first_entry(&vm->freed, | 1691 | mapping = list_first_entry(&vm->freed, |
1669 | struct amdgpu_bo_va_mapping, list); | 1692 | struct amdgpu_bo_va_mapping, list); |
1670 | list_del(&mapping->list); | 1693 | list_del(&mapping->list); |
1671 | 1694 | ||
1672 | if (vm->pte_support_ats) | 1695 | if (vm->pte_support_ats && mapping->start < AMDGPU_VA_HOLE_START) |
1673 | init_pte_value = AMDGPU_PTE_DEFAULT_ATC; | 1696 | init_pte_value = AMDGPU_PTE_DEFAULT_ATC; |
1674 | 1697 | ||
1675 | r = amdgpu_vm_bo_update_mapping(adev, NULL, NULL, vm, | 1698 | r = amdgpu_vm_bo_update_mapping(adev, NULL, NULL, vm, |
@@ -2362,7 +2385,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, | |||
2362 | goto error_free_root; | 2385 | goto error_free_root; |
2363 | 2386 | ||
2364 | r = amdgpu_vm_clear_bo(adev, vm, vm->root.base.bo, | 2387 | r = amdgpu_vm_clear_bo(adev, vm, vm->root.base.bo, |
2365 | adev->vm_manager.root_level); | 2388 | adev->vm_manager.root_level, |
2389 | vm->pte_support_ats); | ||
2366 | if (r) | 2390 | if (r) |
2367 | goto error_unreserve; | 2391 | goto error_unreserve; |
2368 | 2392 | ||