Module Name:    src
Committed By:   riastradh
Date:           Thu May  1 15:19:16 UTC 2014

Modified Files:
        src/sys/external/bsd/drm2/dist/drm/i915: i915_gem.c
        src/sys/external/bsd/drm2/dist/include/drm: drmP.h
        src/sys/external/bsd/drm2/drm: drm_drv.c drm_gem_vm.c drm_vm.c

Log Message:
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!


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c
cvs rdiff -u -r1.3 -r1.4 src/sys/external/bsd/drm2/dist/include/drm/drmP.h
cvs rdiff -u -r1.3 -r1.4 src/sys/external/bsd/drm2/drm/drm_drv.c
cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/drm2/drm/drm_gem_vm.c \
    src/sys/external/bsd/drm2/drm/drm_vm.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c
diff -u src/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c:1.3 src/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c:1.4
--- src/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c:1.3	Sat Apr 26 20:26:26 2014
+++ src/sys/external/bsd/drm2/dist/drm/i915/i915_gem.c	Thu May  1 15:19:16 2014
@@ -1521,12 +1521,14 @@ i915_gem_fault(struct uvm_faultinfo *ufi
 	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)

Index: src/sys/external/bsd/drm2/dist/include/drm/drmP.h
diff -u src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.3 src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.4
--- src/sys/external/bsd/drm2/dist/include/drm/drmP.h:1.3	Thu Apr  3 19:18:29 2014
+++ src/sys/external/bsd/drm2/dist/include/drm/drmP.h	Thu May  1 15:19:16 2014
@@ -1495,7 +1495,7 @@ extern int drm_release(struct inode *ino
 				/* 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_object_handle_free(struct d
 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);

Index: src/sys/external/bsd/drm2/drm/drm_drv.c
diff -u src/sys/external/bsd/drm2/drm/drm_drv.c:1.3 src/sys/external/bsd/drm2/drm/drm_drv.c:1.4
--- src/sys/external/bsd/drm2/drm/drm_drv.c:1.3	Fri Apr  4 15:16:59 2014
+++ src/sys/external/bsd/drm2/drm/drm_drv.c	Thu May  1 15:19:16 2014
@@ -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 @@ drm_mmap_ioctl(struct drm_device *dev, v
 	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 @@ drm_mmap_ioctl(struct drm_device *dev, v
 		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 @@ map:	vm_prot = ((ISSET(prot, PROT_READ)?
 	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;

Index: src/sys/external/bsd/drm2/drm/drm_gem_vm.c
diff -u src/sys/external/bsd/drm2/drm/drm_gem_vm.c:1.2 src/sys/external/bsd/drm2/drm/drm_gem_vm.c:1.3
--- src/sys/external/bsd/drm2/drm/drm_gem_vm.c:1.2	Tue Mar 18 18:20:42 2014
+++ src/sys/external/bsd/drm2/drm/drm_gem_vm.c	Thu May  1 15:19:16 2014
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: drm_gem_vm.c
 #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 @@ drm_gem_pager_detach(struct uvm_object *
 
 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 @@ drm_gem_mmap_object(struct drm_device *d
 
 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 @@ drm_gem_mmap_object_locked(struct drm_de
 	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 @@ drm_gem_mmap_object_locked(struct drm_de
 	/* Success!  */
 	drm_gem_object_reference(obj);
 	*uobjp = &obj->gemo_uvmobj;
+	*uoffsetp = 0;
 	return 0;
 }
Index: src/sys/external/bsd/drm2/drm/drm_vm.c
diff -u src/sys/external/bsd/drm2/drm/drm_vm.c:1.2 src/sys/external/bsd/drm2/drm/drm_vm.c:1.3
--- src/sys/external/bsd/drm2/drm/drm_vm.c:1.2	Tue Mar 18 18:20:42 2014
+++ src/sys/external/bsd/drm2/drm/drm_vm.c	Thu May  1 15:19:16 2014
@@ -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 @@ static paddr_t	drm_mmap_map_paddr(struct
 
 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 @@ drm_mmap_paddr(struct drm_device *dev, o
 {
 	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 @@ drm_mmap_paddr_locked(struct drm_device 
 	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 @@ drm_mmap_paddr_locked(struct drm_device 
 	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 @@ drm_mmap_dma_paddr(struct drm_device *de
 	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 @@ drm_mmap_map_paddr(struct drm_device *de
 {
 	int flags = 0;
 
+	KASSERT(byte_offset <= map->size);
+
 	switch (map->type) {
 	case _DRM_FRAME_BUFFER:
 	case _DRM_AGP:

Reply via email to