diff options
author | Christian König <christian.koenig@amd.com> | 2017-01-27 09:58:43 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2017-02-02 13:50:03 -0500 |
commit | 2ffdaafb5d5f37bf66da1b775333a7abc2b69563 (patch) | |
tree | 799aa6a9627fdade2632fbff8fc14d6d0900d7cc /drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | |
parent | 18566acac18f5784347bc5fe636a26897d1c963b (diff) |
drm/amdgpu: fix race in GEM VA map IOCTL v2
Somebody could try to free the bo_va between mapping and updating it.
v2: fix typos in comment
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 47 |
1 files changed, 15 insertions, 32 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 9bd1b4eae32e..4acb9c5e8b64 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | |||
@@ -487,67 +487,50 @@ static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo) | |||
487 | * | 487 | * |
488 | * @adev: amdgpu_device pointer | 488 | * @adev: amdgpu_device pointer |
489 | * @bo_va: bo_va to update | 489 | * @bo_va: bo_va to update |
490 | * @list: validation list | ||
491 | * @operation: map or unmap | ||
490 | * | 492 | * |
491 | * Update the bo_va directly after setting it's address. Errors are not | 493 | * Update the bo_va directly after setting its address. Errors are not |
492 | * vital here, so they are not reported back to userspace. | 494 | * vital here, so they are not reported back to userspace. |
493 | */ | 495 | */ |
494 | static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, | 496 | static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, |
495 | struct amdgpu_bo_va *bo_va, | 497 | struct amdgpu_bo_va *bo_va, |
498 | struct list_head *list, | ||
496 | uint32_t operation) | 499 | uint32_t operation) |
497 | { | 500 | { |
498 | struct ttm_validate_buffer tv, *entry; | 501 | struct ttm_validate_buffer *entry; |
499 | struct amdgpu_bo_list_entry vm_pd; | 502 | int r = -ERESTARTSYS; |
500 | struct ww_acquire_ctx ticket; | ||
501 | struct list_head list, duplicates; | ||
502 | int r; | ||
503 | |||
504 | INIT_LIST_HEAD(&list); | ||
505 | INIT_LIST_HEAD(&duplicates); | ||
506 | |||
507 | tv.bo = &bo_va->bo->tbo; | ||
508 | tv.shared = true; | ||
509 | list_add(&tv.head, &list); | ||
510 | |||
511 | amdgpu_vm_get_pd_bo(bo_va->vm, &list, &vm_pd); | ||
512 | |||
513 | /* Provide duplicates to avoid -EALREADY */ | ||
514 | r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates); | ||
515 | if (r) | ||
516 | goto error_print; | ||
517 | 503 | ||
518 | list_for_each_entry(entry, &list, head) { | 504 | list_for_each_entry(entry, list, head) { |
519 | struct amdgpu_bo *bo = | 505 | struct amdgpu_bo *bo = |
520 | container_of(entry->bo, struct amdgpu_bo, tbo); | 506 | container_of(entry->bo, struct amdgpu_bo, tbo); |
521 | 507 | ||
522 | /* if anything is swapped out don't swap it in here, | 508 | /* if anything is swapped out don't swap it in here, |
523 | just abort and wait for the next CS */ | 509 | just abort and wait for the next CS */ |
524 | if (!amdgpu_bo_gpu_accessible(bo)) | 510 | if (!amdgpu_bo_gpu_accessible(bo)) |
525 | goto error_unreserve; | 511 | goto error; |
526 | 512 | ||
527 | if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow)) | 513 | if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow)) |
528 | goto error_unreserve; | 514 | goto error; |
529 | } | 515 | } |
530 | 516 | ||
531 | r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check, | 517 | r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check, |
532 | NULL); | 518 | NULL); |
533 | if (r) | 519 | if (r) |
534 | goto error_unreserve; | 520 | goto error; |
535 | 521 | ||
536 | r = amdgpu_vm_update_page_directory(adev, bo_va->vm); | 522 | r = amdgpu_vm_update_page_directory(adev, bo_va->vm); |
537 | if (r) | 523 | if (r) |
538 | goto error_unreserve; | 524 | goto error; |
539 | 525 | ||
540 | r = amdgpu_vm_clear_freed(adev, bo_va->vm); | 526 | r = amdgpu_vm_clear_freed(adev, bo_va->vm); |
541 | if (r) | 527 | if (r) |
542 | goto error_unreserve; | 528 | goto error; |
543 | 529 | ||
544 | if (operation == AMDGPU_VA_OP_MAP) | 530 | if (operation == AMDGPU_VA_OP_MAP) |
545 | r = amdgpu_vm_bo_update(adev, bo_va, false); | 531 | r = amdgpu_vm_bo_update(adev, bo_va, false); |
546 | 532 | ||
547 | error_unreserve: | 533 | error: |
548 | ttm_eu_backoff_reservation(&ticket, &list); | ||
549 | |||
550 | error_print: | ||
551 | if (r && r != -ERESTARTSYS) | 534 | if (r && r != -ERESTARTSYS) |
552 | DRM_ERROR("Couldn't update BO_VA (%d)\n", r); | 535 | DRM_ERROR("Couldn't update BO_VA (%d)\n", r); |
553 | } | 536 | } |
@@ -640,10 +623,10 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, | |||
640 | default: | 623 | default: |
641 | break; | 624 | break; |
642 | } | 625 | } |
643 | ttm_eu_backoff_reservation(&ticket, &list); | ||
644 | if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) && | 626 | if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) && |
645 | !amdgpu_vm_debug) | 627 | !amdgpu_vm_debug) |
646 | amdgpu_gem_va_update_vm(adev, bo_va, args->operation); | 628 | amdgpu_gem_va_update_vm(adev, bo_va, &list, args->operation); |
629 | ttm_eu_backoff_reservation(&ticket, &list); | ||
647 | 630 | ||
648 | drm_gem_object_unreference_unlocked(gobj); | 631 | drm_gem_object_unreference_unlocked(gobj); |
649 | return r; | 632 | return r; |