diff options
author | Christian König <christian.koenig@amd.com> | 2016-03-03 08:24:57 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2016-03-08 11:01:46 -0500 |
commit | 637dd3b5ca9e0d38b046f04e97a1d2f7523e7e25 (patch) | |
tree | 6986a05d8ae674d2b2bcae6fb0ccbf2a198971d8 /drivers/gpu/drm/amd/amdgpu | |
parent | 211dff5518d938d0c11205af3113d2c7a292dd98 (diff) |
drm/amdgpu: prevent get_user_pages recursion
Remember the tasks which are inside get_user_pages()
and ignore MMU callbacks from there.
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')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index e52fc641edfb..53e627970798 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |||
@@ -494,13 +494,20 @@ static void amdgpu_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_re | |||
494 | /* | 494 | /* |
495 | * TTM backend functions. | 495 | * TTM backend functions. |
496 | */ | 496 | */ |
497 | struct amdgpu_ttm_gup_task_list { | ||
498 | struct list_head list; | ||
499 | struct task_struct *task; | ||
500 | }; | ||
501 | |||
497 | struct amdgpu_ttm_tt { | 502 | struct amdgpu_ttm_tt { |
498 | struct ttm_dma_tt ttm; | 503 | struct ttm_dma_tt ttm; |
499 | struct amdgpu_device *adev; | 504 | struct amdgpu_device *adev; |
500 | u64 offset; | 505 | u64 offset; |
501 | uint64_t userptr; | 506 | uint64_t userptr; |
502 | struct mm_struct *usermm; | 507 | struct mm_struct *usermm; |
503 | uint32_t userflags; | 508 | uint32_t userflags; |
509 | spinlock_t guptasklock; | ||
510 | struct list_head guptasks; | ||
504 | }; | 511 | }; |
505 | 512 | ||
506 | /* prepare the sg table with the user pages */ | 513 | /* prepare the sg table with the user pages */ |
@@ -530,9 +537,20 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) | |||
530 | unsigned num_pages = ttm->num_pages - pinned; | 537 | unsigned num_pages = ttm->num_pages - pinned; |
531 | uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE; | 538 | uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE; |
532 | struct page **pages = ttm->pages + pinned; | 539 | struct page **pages = ttm->pages + pinned; |
540 | struct amdgpu_ttm_gup_task_list guptask; | ||
541 | |||
542 | guptask.task = current; | ||
543 | spin_lock(>t->guptasklock); | ||
544 | list_add(&guptask.list, >t->guptasks); | ||
545 | spin_unlock(>t->guptasklock); | ||
533 | 546 | ||
534 | r = get_user_pages(current, current->mm, userptr, num_pages, | 547 | r = get_user_pages(current, current->mm, userptr, num_pages, |
535 | write, 0, pages, NULL); | 548 | write, 0, pages, NULL); |
549 | |||
550 | spin_lock(>t->guptasklock); | ||
551 | list_del(&guptask.list); | ||
552 | spin_unlock(>t->guptasklock); | ||
553 | |||
536 | if (r < 0) | 554 | if (r < 0) |
537 | goto release_pages; | 555 | goto release_pages; |
538 | 556 | ||
@@ -783,6 +801,9 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, | |||
783 | gtt->userptr = addr; | 801 | gtt->userptr = addr; |
784 | gtt->usermm = current->mm; | 802 | gtt->usermm = current->mm; |
785 | gtt->userflags = flags; | 803 | gtt->userflags = flags; |
804 | spin_lock_init(>t->guptasklock); | ||
805 | INIT_LIST_HEAD(>t->guptasks); | ||
806 | |||
786 | return 0; | 807 | return 0; |
787 | } | 808 | } |
788 | 809 | ||
@@ -800,18 +821,25 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, | |||
800 | unsigned long end) | 821 | unsigned long end) |
801 | { | 822 | { |
802 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 823 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
824 | struct amdgpu_ttm_gup_task_list *entry; | ||
803 | unsigned long size; | 825 | unsigned long size; |
804 | 826 | ||
805 | if (gtt == NULL) | 827 | if (gtt == NULL || !gtt->userptr) |
806 | return false; | ||
807 | |||
808 | if (gtt->ttm.ttm.state != tt_bound || !gtt->userptr) | ||
809 | return false; | 828 | return false; |
810 | 829 | ||
811 | size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE; | 830 | size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE; |
812 | if (gtt->userptr > end || gtt->userptr + size <= start) | 831 | if (gtt->userptr > end || gtt->userptr + size <= start) |
813 | return false; | 832 | return false; |
814 | 833 | ||
834 | spin_lock(>t->guptasklock); | ||
835 | list_for_each_entry(entry, >t->guptasks, list) { | ||
836 | if (entry->task == current) { | ||
837 | spin_unlock(>t->guptasklock); | ||
838 | return false; | ||
839 | } | ||
840 | } | ||
841 | spin_unlock(>t->guptasklock); | ||
842 | |||
815 | return true; | 843 | return true; |
816 | } | 844 | } |
817 | 845 | ||