Skip to content

Commit

Permalink
drm/i915/gem: Pull phys pread/pwrite implementations to the backend
Browse files Browse the repository at this point in the history
Move the specialised interactions with the physical GEM object from the
pread/pwrite ioctl handler into the phys backend.

Currently, if one is able to exhaust the entire aperture and then try to
pwrite into an object not backed by struct page, we accidentally invoked
the phys pwrite handler on a non-phys object; calamitous.

Fixes: c6790dc ("drm/i915: Wean off drm_pci_alloc/drm_pci_free")
Testcase: igt/gem_pwrite/exhaustion
Signed-off-by: Chris Wilson <[email protected]>
Reviewed-by: Matthew Auld <[email protected]>
Cc: [email protected]
Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
(cherry picked from commit 852e1b3)
Signed-off-by: Rodrigo Vivi <[email protected]>
  • Loading branch information
ickle authored and rodrigovivi committed Nov 13, 2020
1 parent 0a1db6f commit 0eb0feb
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 26 deletions.
55 changes: 55 additions & 0 deletions drivers/gpu/drm/i915/gem/i915_gem_phys.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,58 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
vaddr, dma);
}

static int
phys_pwrite(struct drm_i915_gem_object *obj,
const struct drm_i915_gem_pwrite *args)
{
void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
char __user *user_data = u64_to_user_ptr(args->data_ptr);
int err;

err = i915_gem_object_wait(obj,
I915_WAIT_INTERRUPTIBLE |
I915_WAIT_ALL,
MAX_SCHEDULE_TIMEOUT);
if (err)
return err;

/*
* We manually control the domain here and pretend that it
* remains coherent i.e. in the GTT domain, like shmem_pwrite.
*/
i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);

if (copy_from_user(vaddr, user_data, args->size))
return -EFAULT;

drm_clflush_virt_range(vaddr, args->size);
intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);

i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
return 0;
}

static int
phys_pread(struct drm_i915_gem_object *obj,
const struct drm_i915_gem_pread *args)
{
void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
char __user *user_data = u64_to_user_ptr(args->data_ptr);
int err;

err = i915_gem_object_wait(obj,
I915_WAIT_INTERRUPTIBLE,
MAX_SCHEDULE_TIMEOUT);
if (err)
return err;

drm_clflush_virt_range(vaddr, args->size);
if (copy_to_user(user_data, vaddr, args->size))
return -EFAULT;

return 0;
}

static void phys_release(struct drm_i915_gem_object *obj)
{
fput(obj->base.filp);
Expand All @@ -144,6 +196,9 @@ static const struct drm_i915_gem_object_ops i915_gem_phys_ops = {
.get_pages = i915_gem_object_get_pages_phys,
.put_pages = i915_gem_object_put_pages_phys,

.pread = phys_pread,
.pwrite = phys_pwrite,

.release = phys_release,
};

Expand Down
26 changes: 0 additions & 26 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,30 +179,6 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj,
return ret;
}

static int
i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
struct drm_i915_gem_pwrite *args,
struct drm_file *file)
{
void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
char __user *user_data = u64_to_user_ptr(args->data_ptr);

/*
* We manually control the domain here and pretend that it
* remains coherent i.e. in the GTT domain, like shmem_pwrite.
*/
i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);

if (copy_from_user(vaddr, user_data, args->size))
return -EFAULT;

drm_clflush_virt_range(vaddr, args->size);
intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);

i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
return 0;
}

static int
i915_gem_create(struct drm_file *file,
struct intel_memory_region *mr,
Expand Down Expand Up @@ -872,8 +848,6 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
if (ret == -EFAULT || ret == -ENOSPC) {
if (i915_gem_object_has_struct_page(obj))
ret = i915_gem_shmem_pwrite(obj, args);
else
ret = i915_gem_phys_pwrite(obj, args, file);
}

i915_gem_object_unpin_pages(obj);
Expand Down

0 comments on commit 0eb0feb

Please sign in to comment.