diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0354-drm-amdgpu-prevent-get_user_pages-recursion.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0354-drm-amdgpu-prevent-get_user_pages-recursion.patch | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0354-drm-amdgpu-prevent-get_user_pages-recursion.patch b/common/recipes-kernel/linux/files/0354-drm-amdgpu-prevent-get_user_pages-recursion.patch new file mode 100644 index 00000000..954516b9 --- /dev/null +++ b/common/recipes-kernel/linux/files/0354-drm-amdgpu-prevent-get_user_pages-recursion.patch @@ -0,0 +1,113 @@ +From 497ffcd5b59f717af1147661efe74bb2dca17733 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> +Date: Thu, 3 Mar 2016 14:24:57 +0100 +Subject: [PATCH 0354/1110] drm/amdgpu: prevent get_user_pages recursion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +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> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 48 ++++++++++++++++++++++++++------- + 1 file 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 e5a684e..051cd39 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 + /* + * TTM backend functions. + */ ++struct amdgpu_ttm_gup_task_list { ++ struct list_head list; ++ struct task_struct *task; ++}; ++ + struct amdgpu_ttm_tt { +- struct ttm_dma_tt ttm; +- struct amdgpu_device *adev; +- u64 offset; +- uint64_t userptr; +- struct mm_struct *usermm; +- uint32_t userflags; ++ struct ttm_dma_tt ttm; ++ struct amdgpu_device *adev; ++ u64 offset; ++ uint64_t userptr; ++ struct mm_struct *usermm; ++ uint32_t userflags; ++ spinlock_t guptasklock; ++ struct list_head guptasks; + }; + + /* prepare the sg table with the user pages */ +@@ -530,9 +537,20 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm) + unsigned num_pages = ttm->num_pages - pinned; + uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE; + struct page **pages = ttm->pages + pinned; ++ struct amdgpu_ttm_gup_task_list guptask; ++ ++ guptask.task = current; ++ spin_lock(>t->guptasklock); ++ list_add(&guptask.list, >t->guptasks); ++ spin_unlock(>t->guptasklock); + + r = get_user_pages(current, current->mm, userptr, num_pages, + write, 0, pages, NULL); ++ ++ spin_lock(>t->guptasklock); ++ list_del(&guptask.list); ++ spin_unlock(>t->guptasklock); ++ + if (r < 0) + goto release_pages; + +@@ -783,6 +801,9 @@ int amdgpu_ttm_tt_set_userptr(struct ttm_tt *ttm, uint64_t addr, + gtt->userptr = addr; + gtt->usermm = current->mm; + gtt->userflags = flags; ++ spin_lock_init(>t->guptasklock); ++ INIT_LIST_HEAD(>t->guptasks); ++ + return 0; + } + +@@ -800,18 +821,25 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, + unsigned long end) + { + struct amdgpu_ttm_tt *gtt = (void *)ttm; ++ struct amdgpu_ttm_gup_task_list *entry; + unsigned long size; + +- if (gtt == NULL) +- return false; +- +- if (gtt->ttm.ttm.state != tt_bound || !gtt->userptr) ++ if (gtt == NULL || !gtt->userptr) + return false; + + size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE; + if (gtt->userptr > end || gtt->userptr + size <= start) + return false; + ++ spin_lock(>t->guptasklock); ++ list_for_each_entry(entry, >t->guptasks, list) { ++ if (entry->task == current) { ++ spin_unlock(>t->guptasklock); ++ return false; ++ } ++ } ++ spin_unlock(>t->guptasklock); ++ + return true; + } + +-- +2.7.4 + |