| From c2fd4d3f96d3398d6418723b4a4886a980d2f9a6 Mon Sep 17 00:00:00 2001 |
| From: Matthew Auld <matthew.auld@intel.com> |
| Date: Fri, 17 Jan 2020 13:24:13 +0000 |
| Subject: [PATCH] drm/i915/userptr: fix size calculation |
| |
| commit ecc4d2a52df65479de5e333a9065ed02202a400f upstream. |
| |
| If we create a rather large userptr object(e.g 1ULL << 32) we might |
| shift past the type-width of num_pages: (int)num_pages << PAGE_SHIFT, |
| resulting in a totally bogus sg_table, which fortunately will eventually |
| manifest as: |
| |
| gen8_ppgtt_insert_huge:463 GEM_BUG_ON(iter->sg->length < page_size) |
| kernel BUG at drivers/gpu/drm/i915/gt/gen8_ppgtt.c:463! |
| |
| v2: more unsigned long |
| prefer I915_GTT_PAGE_SIZE |
| |
| Fixes: 5cc9ed4b9a7a ("drm/i915: Introduce mapping of user pages into video memory (userptr) ioctl") |
| Signed-off-by: Matthew Auld <matthew.auld@intel.com> |
| Cc: Chris Wilson <chris@chris-wilson.co.uk> |
| Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> |
| Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> |
| Link: https://patchwork.freedesktop.org/patch/msgid/20200117132413.1170563-2-matthew.auld@intel.com |
| (cherry picked from commit 8e78871bc1e5efec22c950d3fd24ddb63d4ff28a) |
| Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c |
| index 8f460cc4cc1f..04c084508435 100644 |
| --- a/drivers/gpu/drm/i915/i915_gem_gtt.c |
| +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c |
| @@ -988,6 +988,7 @@ gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt, |
| pd = pdp->page_directory[idx->pdpe]; |
| vaddr = kmap_atomic_px(pd->page_table[idx->pde]); |
| do { |
| + GEM_BUG_ON(iter->sg->length < I915_GTT_PAGE_SIZE); |
| vaddr[idx->pte] = pte_encode | iter->dma; |
| |
| iter->dma += I915_GTT_PAGE_SIZE; |
| @@ -1718,6 +1719,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, |
| |
| vaddr = kmap_atomic_px(ppgtt->pd.page_table[act_pt]); |
| do { |
| + GEM_BUG_ON(iter.sg->length < I915_GTT_PAGE_SIZE); |
| vaddr[act_pte] = pte_encode | GEN6_PTE_ADDR_ENCODE(iter.dma); |
| |
| iter.dma += I915_GTT_PAGE_SIZE; |
| diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c |
| index c91ae67a39c3..2e200e832ac8 100644 |
| --- a/drivers/gpu/drm/i915/i915_gem_userptr.c |
| +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c |
| @@ -441,7 +441,7 @@ struct get_pages_work { |
| |
| static struct sg_table * |
| __i915_gem_userptr_alloc_pages(struct drm_i915_gem_object *obj, |
| - struct page **pvec, int num_pages) |
| + struct page **pvec, unsigned long num_pages) |
| { |
| unsigned int max_segment = i915_sg_segment_size(); |
| struct sg_table *st; |
| @@ -487,9 +487,10 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) |
| { |
| struct get_pages_work *work = container_of(_work, typeof(*work), work); |
| struct drm_i915_gem_object *obj = work->obj; |
| - const int npages = obj->base.size >> PAGE_SHIFT; |
| + const unsigned long npages = obj->base.size >> PAGE_SHIFT; |
| + unsigned long pinned; |
| struct page **pvec; |
| - int pinned, ret; |
| + int ret; |
| |
| ret = -ENOMEM; |
| pinned = 0; |
| @@ -592,7 +593,7 @@ __i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj) |
| |
| static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) |
| { |
| - const int num_pages = obj->base.size >> PAGE_SHIFT; |
| + const unsigned long num_pages = obj->base.size >> PAGE_SHIFT; |
| struct mm_struct *mm = obj->userptr.mm->mm; |
| struct page **pvec; |
| struct sg_table *pages; |
| -- |
| 2.7.4 |
| |