Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/external/bsd/drm2 Tweak some DRM GEM page indexing crap.



details:   https://anonhg.NetBSD.org/src/rev/9ecf94e1d134
branches:  trunk
changeset: 795812:9ecf94e1d134
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Thu May 01 15:19:16 2014 +0000

description:
Tweak some DRM GEM page indexing crap.

- Fix order of subtraction in drm_mmap_paddr_locked.
- Address GEM objects' pages from 0, not from the mmap cookie.
- Check page alignment earlier in mmap code paths.
- Sprinkle kasserts throughout.

Still doesn't fix the garbage that is sometimes being scribbled all
over kernel memory!

diffstat:

 sys/external/bsd/drm2/dist/drm/i915/i915_gem.c |   6 ++-
 sys/external/bsd/drm2/dist/include/drm/drmP.h  |   4 +-
 sys/external/bsd/drm2/drm/drm_drv.c            |  15 ++++++----
 sys/external/bsd/drm2/drm/drm_gem_vm.c         |  19 +++++++------
 sys/external/bsd/drm2/drm/drm_vm.c             |  37 ++++++++++++++++---------
 5 files changed, 49 insertions(+), 32 deletions(-)

diffs (287 lines):

diff -r 4acb3a663e17 -r 9ecf94e1d134 sys/external/bsd/drm2/dist/drm/i915/i915_gem.c
--- a/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c    Thu May 01 14:37:36 2014 +0000
+++ b/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c    Thu May 01 15:19:16 2014 +0000
@@ -1521,12 +1521,14 @@
        struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
+       voff_t byte_offset;
        pgoff_t page_offset;
        int ret = 0;
        bool write = ISSET(access_type, VM_PROT_WRITE)? 1 : 0;
 
-       page_offset = (ufi->entry->offset + (vaddr - ufi->entry->start)) >>
-           PAGE_SHIFT;
+       byte_offset = (ufi->entry->offset + (vaddr - ufi->entry->start));
+       KASSERT(byte_offset <= obj->base.size);
+       page_offset = (byte_offset >> PAGE_SHIFT);
 
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
diff -r 4acb3a663e17 -r 9ecf94e1d134 sys/external/bsd/drm2/dist/include/drm/drmP.h
--- a/sys/external/bsd/drm2/dist/include/drm/drmP.h     Thu May 01 14:37:36 2014 +0000
+++ b/sys/external/bsd/drm2/dist/include/drm/drmP.h     Thu May 01 15:19:16 2014 +0000
@@ -1495,7 +1495,7 @@
                                /* Mapping support (drm_vm.h) */
 #ifdef __NetBSD__
 extern int drm_mmap_object(struct drm_device *, off_t, size_t, int,
-    struct uvm_object **);
+    struct uvm_object **, voff_t *);
 extern paddr_t drm_mmap_paddr(struct drm_device *, off_t, int);
 #else
 extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
@@ -1868,7 +1868,7 @@
 void drm_gem_pager_reference(struct uvm_object *);
 void drm_gem_pager_detach(struct uvm_object *);
 int drm_gem_mmap_object(struct drm_device *, off_t, size_t, int,
-    struct uvm_object **);
+    struct uvm_object **, voff_t *);
 #else
 void drm_gem_vm_open(struct vm_area_struct *vma);
 void drm_gem_vm_close(struct vm_area_struct *vma);
diff -r 4acb3a663e17 -r 9ecf94e1d134 sys/external/bsd/drm2/drm/drm_drv.c
--- a/sys/external/bsd/drm2/drm/drm_drv.c       Thu May 01 14:37:36 2014 +0000
+++ b/sys/external/bsd/drm2/drm/drm_drv.c       Thu May 01 15:19:16 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: drm_drv.c,v 1.3 2014/04/04 15:16:59 riastradh Exp $    */
+/*     $NetBSD: drm_drv.c,v 1.4 2014/05/01 15:19:16 riastradh Exp $    */
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.3 2014/04/04 15:16:59 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_drv.c,v 1.4 2014/05/01 15:19:16 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -977,6 +977,7 @@
        const int flags = args->dnm_flags;
        const off_t offset = args->dnm_offset;
        struct uvm_object *uobj;
+       voff_t uoffset;
        const vm_prot_t vm_maxprot = (VM_PROT_READ | VM_PROT_WRITE);
        vm_prot_t vm_prot;
        int uvmflag;
@@ -991,17 +992,19 @@
                return -EACCES;
        if (flags != MAP_SHARED)
                return -EINVAL;
+       if (offset != (offset & ~(PAGE_SIZE-1)))
+               return -EINVAL;
        (void)addr;             /* XXX ignore -- no MAP_FIXED for now */
 
        /* Try a GEM object mapping first.  */
-       ret = drm_gem_mmap_object(dev, offset, size, prot, &uobj);
+       ret = drm_gem_mmap_object(dev, offset, size, prot, &uobj, &uoffset);
        if (ret)
                return ret;
        if (uobj != NULL)
                goto map;
 
        /* Try a traditional DRM mapping second.  */
-       ret = drm_mmap_object(dev, offset, size, prot, &uobj);
+       ret = drm_mmap_object(dev, offset, size, prot, &uobj, &uoffset);
        if (ret)
                return ret;
        if (uobj != NULL)
@@ -1020,8 +1023,8 @@
        vaddr = (*curproc->p_emul->e_vm_default_addr)(curproc,
            (vaddr_t)curproc->p_vmspace->vm_daddr, size);
        /* XXX errno NetBSD->Linux */
-       ret = -uvm_map(&curproc->p_vmspace->vm_map, &vaddr, size, uobj, offset,
-           align, uvmflag);
+       ret = -uvm_map(&curproc->p_vmspace->vm_map, &vaddr, size, uobj,
+           uoffset, align, uvmflag);
        if (ret) {
                (*uobj->pgops->pgo_detach)(uobj);
                return ret;
diff -r 4acb3a663e17 -r 9ecf94e1d134 sys/external/bsd/drm2/drm/drm_gem_vm.c
--- a/sys/external/bsd/drm2/drm/drm_gem_vm.c    Thu May 01 14:37:36 2014 +0000
+++ b/sys/external/bsd/drm2/drm/drm_gem_vm.c    Thu May 01 15:19:16 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: drm_gem_vm.c,v 1.2 2014/03/18 18:20:42 riastradh Exp $ */
+/*     $NetBSD: drm_gem_vm.c,v 1.3 2014/05/01 15:19:16 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_gem_vm.c,v 1.2 2014/03/18 18:20:42 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_gem_vm.c,v 1.3 2014/05/01 15:19:16 riastradh Exp $");
 
 #include <sys/types.h>
 
@@ -39,7 +39,7 @@
 #include <drm/drmP.h>
 
 static int     drm_gem_mmap_object_locked(struct drm_device *, off_t, size_t,
-                   int, struct uvm_object **);
+                   int, struct uvm_object **, voff_t *);
 
 void
 drm_gem_pager_reference(struct uvm_object *uobj)
@@ -61,13 +61,13 @@
 
 int
 drm_gem_mmap_object(struct drm_device *dev, off_t byte_offset, size_t nbytes,
-    int prot, struct uvm_object **uobjp)
+    int prot, struct uvm_object **uobjp, voff_t *uoffsetp)
 {
        int ret;
 
        mutex_lock(&dev->struct_mutex);
        ret = drm_gem_mmap_object_locked(dev, byte_offset, nbytes, prot,
-           uobjp);
+           uobjp, uoffsetp);
        mutex_unlock(&dev->struct_mutex);
 
        return ret;
@@ -75,7 +75,8 @@
 
 static int
 drm_gem_mmap_object_locked(struct drm_device *dev, off_t byte_offset,
-    size_t nbytes, int prot __unused, struct uvm_object **uobjp)
+    size_t nbytes, int prot __unused, struct uvm_object **uobjp,
+    voff_t *uoffsetp)
 {
        struct drm_gem_mm *const mm = dev->mm_private;
        const off_t page_offset = (byte_offset >> PAGE_SHIFT);
@@ -85,13 +86,12 @@
        KASSERT(drm_core_check_feature(dev, DRIVER_GEM));
        KASSERT(dev->driver->gem_uvm_ops != NULL);
        KASSERT(prot == (prot & (PROT_READ | PROT_WRITE)));
-
-       if (byte_offset != (byte_offset & ~(PAGE_SIZE-1))) /* XXX kassert?  */
-               return -EINVAL;
+       KASSERT(byte_offset == (byte_offset & ~(PAGE_SIZE-1)));
 
        if (drm_ht_find_item(&mm->offset_hash, page_offset, &hash) != 0) {
                /* Fall back to vanilla device mappings.  */
                *uobjp = NULL;
+               *uoffsetp = (voff_t)-1;
                return 0;
        }
 
@@ -109,5 +109,6 @@
        /* Success!  */
        drm_gem_object_reference(obj);
        *uobjp = &obj->gemo_uvmobj;
+       *uoffsetp = 0;
        return 0;
 }
diff -r 4acb3a663e17 -r 9ecf94e1d134 sys/external/bsd/drm2/drm/drm_vm.c
--- a/sys/external/bsd/drm2/drm/drm_vm.c        Thu May 01 14:37:36 2014 +0000
+++ b/sys/external/bsd/drm2/drm/drm_vm.c        Thu May 01 15:19:16 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: drm_vm.c,v 1.2 2014/03/18 18:20:42 riastradh Exp $     */
+/*     $NetBSD: drm_vm.c,v 1.3 2014/05/01 15:19:16 riastradh Exp $     */
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: drm_vm.c,v 1.2 2014/03/18 18:20:42 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: drm_vm.c,v 1.3 2014/05/01 15:19:16 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/conf.h>
@@ -47,16 +47,24 @@
 
 int
 drm_mmap_object(struct drm_device *dev, off_t offset, size_t size, int prot,
-    struct uvm_object **uobjp)
+    struct uvm_object **uobjp, voff_t *uoffsetp)
 {
        dev_t devno = cdevsw_lookup_major(&drm_cdevsw);
        struct uvm_object *uobj;
 
+       KASSERT(offset == (offset & ~(PAGE_SIZE-1)));
+
+       /*
+        * Attach the device.  The size and offset are used only for
+        * access checks; offset does not become a base address for the
+        * subsequent uvm_map, hence we set *uoffsetp to offset, not 0.
+        */
        uobj = udv_attach(&devno, prot, offset, size);
        if (uobj == NULL)
                return -EINVAL;
 
        *uobjp = uobj;
+       *uoffsetp = offset;
        return 0;
 }
 
@@ -65,6 +73,9 @@
 {
        paddr_t paddr;
 
+       if (byte_offset != (byte_offset & ~(PAGE_SIZE-1)))
+               return -1;
+
        mutex_lock(&dev->struct_mutex);
        paddr = drm_mmap_paddr_locked(dev, byte_offset, prot);
        mutex_unlock(&dev->struct_mutex);
@@ -79,13 +90,11 @@
        struct drm_hash_item *hash;
 
        KASSERT(mutex_is_locked(&dev->struct_mutex));
-
-       if (byte_offset != (byte_offset & ~(PAGE_SIZE-1)))
-               return -1;
+       KASSERT(byte_offset == (byte_offset & ~(PAGE_SIZE-1)));
 
        if ((dev->dma != NULL) &&
            (0 <= byte_offset) &&
-           (byte_offset <= (dev->dma->page_count << PAGE_SHIFT)))
+           (page_offset <= dev->dma->page_count))
                return drm_mmap_dma_paddr(dev, byte_offset, prot);
 
        if (drm_ht_find_item(&dev->map_hash, page_offset, &hash))
@@ -105,11 +114,12 @@
        if (ISSET(map->flags, _DRM_RESTRICTED) && !DRM_SUSER())
                return -1;
 
-       if (byte_offset < map->offset)
+       if (!(map->offset <= byte_offset))
+               return -1;
+       if (map->size < (map->offset - byte_offset))
                return -1;
 
-       return drm_mmap_map_paddr(dev, map, (map->offset - byte_offset),
-           prot);
+       return drm_mmap_map_paddr(dev, map, (byte_offset - map->offset), prot);
 }
 
 static paddr_t
@@ -118,13 +128,12 @@
        const off_t page_offset = (byte_offset >> PAGE_SHIFT);
 
        KASSERT(mutex_is_locked(&dev->struct_mutex));
+       KASSERT(byte_offset == (byte_offset & ~(PAGE_SIZE-1)));
+       KASSERT(page_offset <= dev->dma->page_count);
 
        if (dev->dma->pagelist == NULL)
                return (paddr_t)-1;
 
-       if (page_offset >= dev->dma->page_count)
-               return (paddr_t)-1;
-
        return dev->dma->pagelist[page_offset];
 }
 
@@ -134,6 +143,8 @@
 {
        int flags = 0;
 
+       KASSERT(byte_offset <= map->size);
+
        switch (map->type) {
        case _DRM_FRAME_BUFFER:
        case _DRM_AGP:



Home | Main Index | Thread Index | Old Index