Module Name:    src
Committed By:   riastradh
Date:           Sun Dec 19 12:26:55 UTC 2021

Modified Files:
        src/sys/external/bsd/drm2/dist/drm/i915/gem: i915_gem_mman.c
            i915_gem_object_types.h

Log Message:
i915: Rearrange how mmap offsets work.

Rather than use the magic offsets in each GEM object's uvm object
itself, just create a separate uvm object for each mapping type and
start at zero within each uvm object.  This should avoid problems
with things like ubc_uiomove which don't know to adjust the starting
offset.


To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 \
    src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_mman.c
cvs rdiff -u -r1.6 -r1.7 \
    src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_object_types.h

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/gem/i915_gem_mman.c
diff -u src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_mman.c:1.20 src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_mman.c:1.21
--- src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_mman.c:1.20	Sun Dec 19 12:13:31 2021
+++ src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_mman.c	Sun Dec 19 12:26:55 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: i915_gem_mman.c,v 1.20 2021/12/19 12:13:31 riastradh Exp $	*/
+/*	$NetBSD: i915_gem_mman.c,v 1.21 2021/12/19 12:26:55 riastradh Exp $	*/
 
 /*
  * SPDX-License-Identifier: MIT
@@ -7,7 +7,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: i915_gem_mman.c,v 1.20 2021/12/19 12:13:31 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i915_gem_mman.c,v 1.21 2021/12/19 12:26:55 riastradh Exp $");
 
 #include <linux/anon_inodes.h>
 #include <linux/mman.h>
@@ -28,7 +28,9 @@ __KERNEL_RCSID(0, "$NetBSD: i915_gem_mma
 #include "i915_user_extensions.h"
 #include "i915_vma.h"
 
-#ifndef __NetBSD__
+#ifdef __NetBSD__
+static const struct uvm_pagerops i915_mmo_gem_uvm_ops;
+#else
 static inline bool
 __vma_matches(struct vm_area_struct *vma, struct file *filp,
 	      unsigned long addr, unsigned long size)
@@ -338,8 +340,6 @@ static vm_fault_t vm_fault_cpu(struct vm
 	paddr_t paddr;
 	int i;
 
-	startpage -= drm_vma_node_start(&mmo->vma_node);
-
 	for (i = 0; i < npages; i++) {
 		if ((flags & PGO_ALLPAGES) == 0 && i != centeridx)
 			continue;
@@ -411,7 +411,6 @@ static vm_fault_t vm_fault_gtt(struct vm
 #ifdef __NetBSD__
 	page_offset = (ufi->entry->offset + (vaddr - ufi->entry->start))
 	    >> PAGE_SHIFT;
-	page_offset -= drm_vma_node_start(&mmo->vma_node);
 #else
 	/* We don't use vmf->pgoff since that has the fake offset */
 	page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT;
@@ -546,14 +545,9 @@ i915_gem_fault(struct uvm_faultinfo *ufi
     int npages, int centeridx, vm_prot_t access_type, int flags)
 {
 	struct uvm_object *uobj = ufi->entry->object.uvm_obj;
-	voff_t uoffset;
-	unsigned long startpage;
-	struct drm_gem_object *gem =
-	    container_of(uobj, struct drm_gem_object, gemo_uvmobj);
-	struct drm_i915_gem_object *obj = to_intel_bo(gem);
-	struct drm_device *dev = obj->base.dev;
-	struct drm_vma_offset_node *node;
-	struct i915_mmap_offset *mmo;
+	struct i915_mmap_offset *mmo =
+	    container_of(uobj, struct i915_mmap_offset, uobj);
+	struct drm_i915_gem_object *obj = mmo->obj;
 	bool pinned = false;
 	int error;
 
@@ -574,44 +568,6 @@ i915_gem_fault(struct uvm_faultinfo *ufi
 	 */
 	rw_exit(obj->base.filp->vmobjlock);
 
-	KASSERT(ufi->entry->start <= vaddr);
-	KASSERT((ufi->entry->offset & (PAGE_SIZE - 1)) == 0);
-	uoffset = ufi->entry->offset + (vaddr - ufi->entry->start);
-	startpage = uoffset >> PAGE_SHIFT;
-
-	/*
-	 * Look up the mmo again because we can't conveniently store it
-	 * alongside the mapping unless we create a separate uvm object
-	 * for it.  XXX Consider creating a separate uvm object as a
-	 * kind of subobject of the main object.
-	 *
-	 * We use drm_vma_offset_lookup_locked because the number of
-	 * pages we're faulting in here may be different from the
-	 * number of pages that were mapped.
-	 */
-	rcu_read_lock();
-	drm_vma_offset_lock_lookup(dev->vma_offset_manager);
-	node = drm_vma_offset_lookup_locked(dev->vma_offset_manager,
-	    startpage, npages);
-	drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
-	rcu_read_unlock();
-
-	/*
-	 * The mmo had better be there -- hope we can't remove the mmo
-	 * without unmapping first!
-	 */
-	KASSERT(node);
-	KASSERTMSG((ufi->entry->offset >> PAGE_SHIFT ==
-		drm_vma_node_start(node)),
-	    /*
-	     * Always provided by i915_gem_mmap_object, but in
-	     * principle we could relax this.
-	     */
-	    "map startpage=%lx =/= node startpage=%lx",
-	    ufi->entry->offset >> PAGE_SHIFT, drm_vma_node_start(node));
-	mmo = container_of(node, struct i915_mmap_offset, vma_node);
-	KASSERT(obj == mmo->obj);
-
 	/* XXX errno Linux->NetBSD */
 	error = -i915_gem_object_pin_pages(obj);
 	if (error)
@@ -814,6 +770,7 @@ insert_mmo(struct drm_i915_gem_object *o
 	if (to_free) {
 		drm_vma_offset_remove(obj->base.dev->vma_offset_manager,
 		    &to_free->vma_node);
+		uvm_obj_destroy(&to_free->uobj, /*free lock*/true);
 		drm_vma_node_destroy(&to_free->vma_node);
 		kfree(to_free);
 	}
@@ -873,6 +830,9 @@ mmap_offset_attach(struct drm_i915_gem_o
 	mmo->mmap_type = mmap_type;
 #ifdef __NetBSD__
 	drm_vma_node_init(&mmo->vma_node);
+	uvm_obj_init(&mmo->uobj, &i915_mmo_gem_uvm_ops, /*allocate lock*/false,
+	    /*nrefs*/1);
+	uvm_obj_setlock(&mmo->uobj, obj->base.filp->vmobjlock);
 #else
 	drm_vma_node_reset(&mmo->vma_node);
 #endif
@@ -902,6 +862,9 @@ out:
 	return mmo;
 
 err:
+#ifdef __NetBSD__
+	uvm_obj_destroy(&mmo->uobj, /*free lock*/true);
+#endif
 	drm_vma_node_destroy(&mmo->vma_node);
 	kfree(mmo);
 	return ERR_PTR(err);
@@ -1036,9 +999,43 @@ i915_gem_mmap_offset_ioctl(struct drm_de
 
 #ifdef __NetBSD__
 
+static int
+i915_gem_nofault(struct uvm_faultinfo *ufi, vaddr_t vaddr,
+    struct vm_page **pps, int npages, int centeridx, vm_prot_t access_type,
+    int flags)
+{
+	panic("i915 main gem object should not be mmapped directly");
+}
+
 const struct uvm_pagerops i915_gem_uvm_ops = {
 	.pgo_reference = drm_gem_pager_reference,
 	.pgo_detach = drm_gem_pager_detach,
+	.pgo_fault = i915_gem_nofault,
+};
+
+static void
+i915_mmo_reference(struct uvm_object *uobj)
+{
+	struct i915_mmap_offset *mmo =
+	    container_of(uobj, struct i915_mmap_offset, uobj);
+	struct drm_i915_gem_object *obj = mmo->obj;
+
+	drm_gem_object_get(&obj->base);
+}
+
+static void
+i915_mmo_detach(struct uvm_object *uobj)
+{
+	struct i915_mmap_offset *mmo =
+	    container_of(uobj, struct i915_mmap_offset, uobj);
+	struct drm_i915_gem_object *obj = mmo->obj;
+
+	drm_gem_object_put_unlocked(&obj->base);
+}
+
+static const struct uvm_pagerops i915_mmo_gem_uvm_ops = {
+	.pgo_reference = i915_mmo_reference,
+	.pgo_detach = i915_mmo_detach,
 	.pgo_fault = i915_gem_fault,
 };
 
@@ -1082,8 +1079,8 @@ i915_gem_mmap_object(struct drm_device *
 	}
 
 	/* Success!  */
-	*uobjp = &obj->base.gemo_uvmobj;
-	*uoffsetp = (voff_t)startpage << PAGE_SHIFT;
+	*uobjp = &mmo->uobj;
+	*uoffsetp = 0;
 	return 0;
 }
 

Index: src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_object_types.h
diff -u src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_object_types.h:1.6 src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_object_types.h:1.7
--- src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_object_types.h:1.6	Sun Dec 19 11:33:30 2021
+++ src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_object_types.h	Sun Dec 19 12:26:55 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: i915_gem_object_types.h,v 1.6 2021/12/19 11:33:30 riastradh Exp $	*/
+/*	$NetBSD: i915_gem_object_types.h,v 1.7 2021/12/19 12:26:55 riastradh Exp $	*/
 
 /*
  * SPDX-License-Identifier: MIT
@@ -78,7 +78,11 @@ struct i915_mmap_offset {
 	struct drm_i915_gem_object *obj;
 	enum i915_mmap_type mmap_type;
 
+#ifdef __NetBSD__
+	struct uvm_object uobj;
+#else
 	struct rb_node offset;
+#endif
 };
 
 struct drm_i915_gem_object {

Reply via email to