Module Name: src
Committed By: riastradh
Date: Sun Dec 19 11:57:43 UTC 2021
Modified Files:
src/sys/external/bsd/drm2/dist/drm/i915/gem: i915_gem_mman.c
src/sys/external/bsd/drm2/i915drm: files.i915drmkms
src/sys/external/bsd/drm2/include/linux: io-mapping.h
Log Message:
i915: Draft gem fault.
To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 \
src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_mman.c
cvs rdiff -u -r1.83 -r1.84 src/sys/external/bsd/drm2/i915drm/files.i915drmkms
cvs rdiff -u -r1.8 -r1.9 src/sys/external/bsd/drm2/include/linux/io-mapping.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.8 src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_mman.c:1.9
--- src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_mman.c:1.8 Sun Dec 19 11:56:52 2021
+++ src/sys/external/bsd/drm2/dist/drm/i915/gem/i915_gem_mman.c Sun Dec 19 11:57:42 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: i915_gem_mman.c,v 1.8 2021/12/19 11:56:52 riastradh Exp $ */
+/* $NetBSD: i915_gem_mman.c,v 1.9 2021/12/19 11:57:42 riastradh Exp $ */
/*
* SPDX-License-Identifier: MIT
@@ -7,7 +7,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: i915_gem_mman.c,v 1.8 2021/12/19 11:56:52 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: i915_gem_mman.c,v 1.9 2021/12/19 11:57:42 riastradh Exp $");
#include <linux/anon_inodes.h>
#include <linux/mman.h>
@@ -239,16 +239,22 @@ compute_partial_view(const struct drm_i9
}
#ifdef __NetBSD__
+/*
+ * XXX pmap_enter_default instead of pmap_enter because of a problem
+ * with using weak aliases in kernel modules.
+ *
+ * XXX This probably won't work in a Xen kernel! Maybe this should be
+ * #ifdef _MODULE?
+ */
+int pmap_enter_default(pmap_t, vaddr_t, paddr_t, vm_prot_t, unsigned);
+#define pmap_enter pmap_enter_default
static int
-i915_gem_fault(struct uvm_faultinfo *ufi, vaddr_t vaddr, struct vm_page **pps,
- int npages, int centeridx, vm_prot_t access_type, int flags)
+i915_error_to_vmf_fault(int err)
{
- panic("NYI");
+ return err;
}
-
#else
-
static vm_fault_t i915_error_to_vmf_fault(int err)
{
switch (err) {
@@ -277,19 +283,36 @@ static vm_fault_t i915_error_to_vmf_faul
return VM_FAULT_NOPAGE;
}
}
+#endif
+#ifdef __NetBSD__
+static int
+vm_fault_cpu(struct uvm_faultinfo *ufi, struct i915_mmap_offset *mmo,
+ vaddr_t vaddr, struct vm_page **pps, int npages, int centeridx, int flags)
+#else
static vm_fault_t vm_fault_cpu(struct vm_fault *vmf)
+#endif
{
+#ifndef __NetBSD__
struct vm_area_struct *area = vmf->vma;
struct i915_mmap_offset *mmo = area->vm_private_data;
+#endif
struct drm_i915_gem_object *obj = mmo->obj;
+#ifdef __NetBSD__
+ bool write = ufi->entry->protection & VM_PROT_WRITE;
+#else
+ bool write = area->vm_flags & VM_WRITE;
+#endif
resource_size_t iomap;
int err;
/* Sanity check that we allow writing into this object */
- if (unlikely(i915_gem_object_is_readonly(obj) &&
- area->vm_flags & VM_WRITE))
+ if (unlikely(i915_gem_object_is_readonly(obj) && write))
+#ifdef __NetBSD__
+ return -EFAULT;
+#else
return VM_FAULT_SIGBUS;
+#endif
err = i915_gem_object_pin_pages(obj);
if (err)
@@ -302,11 +325,38 @@ static vm_fault_t vm_fault_cpu(struct vm
}
/* PTEs are revoked in obj->ops->put_pages() */
+#ifdef __NetBSD__
+ /* XXX No lmem supported yet. */
+ KASSERT(i915_gem_object_type_has(obj,
+ I915_GEM_OBJECT_HAS_STRUCT_PAGE));
+
+ struct scatterlist *sg = obj->mm.pages->sgl;
+ unsigned startpage = (ufi->entry->offset + (vaddr - ufi->entry->start))
+ >> PAGE_SHIFT;
+ paddr_t paddr;
+ int i;
+
+ for (i = 0; i < npages; i++) {
+ if ((flags & PGO_ALLPAGES) == 0 && i != centeridx)
+ continue;
+ if (pps[i] == PGO_DONTCARE)
+ continue;
+ paddr = page_to_phys(sg->sg_pgs[startpage + i]);
+ /* XXX errno NetBSD->Linux */
+ err = -pmap_enter(ufi->orig_map->pmap,
+ vaddr + i*PAGE_SIZE, paddr, ufi->entry->protection,
+ PMAP_CANFAIL | ufi->entry->protection);
+ if (err)
+ break;
+ }
+ pmap_update(ufi->orig_map->pmap);
+#else
err = remap_io_sg(area,
area->vm_start, area->vm_end - area->vm_start,
obj->mm.pages->sgl, iomap);
+#endif
- if (area->vm_flags & VM_WRITE) {
+ if (write) {
GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
obj->mm.dirty = true;
}
@@ -317,17 +367,29 @@ out:
return i915_error_to_vmf_fault(err);
}
+#ifdef __NetBSD__
+static int
+vm_fault_gtt(struct uvm_faultinfo *ufi, struct i915_mmap_offset *mmo,
+ vaddr_t vaddr, struct vm_page **pps, int npages, int centeridx, int flags)
+#else
static vm_fault_t vm_fault_gtt(struct vm_fault *vmf)
+#endif
{
#define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT)
+#ifndef __NetBSD__
struct vm_area_struct *area = vmf->vma;
struct i915_mmap_offset *mmo = area->vm_private_data;
+#endif
struct drm_i915_gem_object *obj = mmo->obj;
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *i915 = to_i915(dev);
struct intel_runtime_pm *rpm = &i915->runtime_pm;
struct i915_ggtt *ggtt = &i915->ggtt;
+#ifdef __NetBSD__
+ bool write = ufi->entry->protection & VM_PROT_WRITE;
+#else
bool write = area->vm_flags & VM_WRITE;
+#endif
intel_wakeref_t wakeref;
struct i915_vma *vma;
pgoff_t page_offset;
@@ -336,10 +398,19 @@ static vm_fault_t vm_fault_gtt(struct vm
/* Sanity check that we allow writing into this object */
if (i915_gem_object_is_readonly(obj) && write)
+#ifdef __NetBSD__
+ return -EFAULT;
+#else
return VM_FAULT_SIGBUS;
+#endif
+#ifdef __NetBSD__
+ page_offset = (ufi->entry->offset + (vaddr - ufi->entry->start))
+ >> PAGE_SHIFT;
+#else
/* We don't use vmf->pgoff since that has the fake offset */
page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT;
+#endif
trace_i915_gem_object_fault(obj, page_offset, true, write);
@@ -399,11 +470,33 @@ static vm_fault_t vm_fault_gtt(struct vm
goto err_unpin;
/* Finally, remap it using the new GTT offset */
+#ifdef __NetBSD__
+ unsigned startpage = page_offset;
+ paddr_t paddr;
+ int i;
+
+ for (i = 0; i < npages; i++) {
+ if ((flags & PGO_ALLPAGES) == 0 && i != centeridx)
+ continue;
+ if (pps[i] == PGO_DONTCARE)
+ continue;
+ paddr = ggtt->gmadr.start + vma->node.start
+ + (startpage + i)*PAGE_SIZE;
+ /* XXX errno NetBSD->Linux */
+ ret = -pmap_enter(ufi->orig_map->pmap,
+ vaddr + i*PAGE_SIZE, paddr, ufi->entry->protection,
+ PMAP_CANFAIL | ufi->entry->protection);
+ if (ret)
+ break;
+ }
+ pmap_update(ufi->orig_map->pmap);
+#else
ret = remap_io_mapping(area,
area->vm_start + (vma->ggtt_view.partial.offset << PAGE_SHIFT),
(ggtt->gmadr.start + vma->node.start) >> PAGE_SHIFT,
min_t(u64, vma->size, area->vm_end - area->vm_start),
&ggtt->iomap);
+#endif
if (ret)
goto err_fence;
@@ -441,7 +534,94 @@ err:
return i915_error_to_vmf_fault(ret);
}
-#endif /* __NetBSD__ */
+#ifdef __NetBSD__
+
+static int
+i915_gem_fault(struct uvm_faultinfo *ufi, vaddr_t vaddr, struct vm_page **pps,
+ int npages, int centeridx, vm_prot_t access_type, int flags)
+{
+ struct uvm_object *uobj = ufi->entry->object.uvm_obj;
+ 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;
+ bool pinned = false;
+ int error;
+
+ KASSERT(rw_lock_held(obj->base.filp->vmobjlock));
+ KASSERT(!i915_gem_object_is_readonly(obj) ||
+ (access_type & VM_PROT_WRITE) == 0);
+ KASSERT(i915_gem_object_type_has(obj,
+ I915_GEM_OBJECT_HAS_STRUCT_PAGE|I915_GEM_OBJECT_HAS_IOMEM));
+
+ /* Actually we don't support iomem right now! */
+ KASSERT(i915_gem_object_type_has(obj,
+ I915_GEM_OBJECT_HAS_STRUCT_PAGE));
+
+ /*
+ * 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.
+ */
+ rcu_read_lock();
+ drm_vma_offset_lock_lookup(dev->vma_offset_manager);
+ node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
+ ufi->entry->start >> PAGE_SHIFT,
+ (ufi->entry->end - ufi->entry->start) >> PAGE_SHIFT);
+ 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);
+ 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)
+ goto out;
+ pinned = true;
+
+ switch (mmo->mmap_type) {
+ case I915_MMAP_TYPE_WC:
+ case I915_MMAP_TYPE_WB:
+ case I915_MMAP_TYPE_UC:
+ /* XXX errno Linux->NetBSD */
+ error = -vm_fault_cpu(ufi, mmo, vaddr, pps, npages, centeridx,
+ flags);
+ break;
+ case I915_MMAP_TYPE_GTT:
+ error = -vm_fault_gtt(ufi, mmo, vaddr, pps, npages, centeridx,
+ flags);
+ break;
+ default:
+ panic("invalid i915 gem mmap offset type: %d",
+ mmo->mmap_type);
+ }
+
+out: if (pinned)
+ i915_gem_object_unpin_pages(obj);
+ uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap, uobj);
+
+ /*
+ * Remap EINTR to success, so that we return to userland.
+ * On the way out, we'll deliver the signal, and if the signal
+ * is not fatal then the user code which faulted will most likely
+ * fault again, and we'll come back here for another try.
+ */
+ if (error == EINTR)
+ error = 0;
+
+ return error;
+}
+
+#endif
void __i915_gem_object_release_mmap_gtt(struct drm_i915_gem_object *obj)
{
Index: src/sys/external/bsd/drm2/i915drm/files.i915drmkms
diff -u src/sys/external/bsd/drm2/i915drm/files.i915drmkms:1.83 src/sys/external/bsd/drm2/i915drm/files.i915drmkms:1.84
--- src/sys/external/bsd/drm2/i915drm/files.i915drmkms:1.83 Sun Dec 19 11:52:07 2021
+++ src/sys/external/bsd/drm2/i915drm/files.i915drmkms Sun Dec 19 11:57:42 2021
@@ -1,4 +1,4 @@
-# $NetBSD: files.i915drmkms,v 1.83 2021/12/19 11:52:07 riastradh Exp $
+# $NetBSD: files.i915drmkms,v 1.84 2021/12/19 11:57:42 riastradh Exp $
version 20180827
@@ -35,6 +35,7 @@ makeoptions i915drmkms "CPPFLAGS.i915drm
makeoptions i915drmkms "CPPFLAGS.i915drmkms"+="-DCONFIG_DRM_I915_PREEMPT_TIMEOUT=640" # milliseconds
makeoptions i915drmkms "CPPFLAGS.i915drmkms"+="-DCONFIG_DRM_I915_CAPTURE_ERROR=0"
makeoptions i915drmkms "CPPFLAGS.i915drmkms"+="-DCONFIG_DRM_I915_SELFTEST=0"
+makeoptions i915drmkms "CPPFLAGS.i915drmkms"+="-DCONFIG_DRM_I915_USERFAULT_AUTOSUSPEND=0"
makeoptions i915drmkms "CPPFLAGS.i915drmkms"+="-DCONFIG_PM=1"
makeoptions i915drmkms "CPPFLAGS.i915drmkms"+="-DCONFIG_INTEL_MEI_HDCP=0"
Index: src/sys/external/bsd/drm2/include/linux/io-mapping.h
diff -u src/sys/external/bsd/drm2/include/linux/io-mapping.h:1.8 src/sys/external/bsd/drm2/include/linux/io-mapping.h:1.9
--- src/sys/external/bsd/drm2/include/linux/io-mapping.h:1.8 Sun Dec 19 11:39:56 2021
+++ src/sys/external/bsd/drm2/include/linux/io-mapping.h Sun Dec 19 11:57:43 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: io-mapping.h,v 1.8 2021/12/19 11:39:56 riastradh Exp $ */
+/* $NetBSD: io-mapping.h,v 1.9 2021/12/19 11:57:43 riastradh Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
struct io_mapping {
bus_space_tag_t diom_bst;
- bus_addr_t diom_addr;
+ bus_addr_t base; /* Linux API */
bus_size_t size; /* Linux API */
vaddr_t diom_va;
bool diom_mapped;
@@ -75,7 +75,7 @@ bus_space_io_mapping_init_wc(bus_space_t
/* Initialize the mapping record. */
mapping->diom_bst = bst;
- mapping->diom_addr = addr;
+ mapping->base = addr;
mapping->size = size;
mapping->diom_mapped = false;
@@ -133,7 +133,7 @@ io_mapping_map_wc(struct io_mapping *map
KASSERT(__type_fit(off_t, offset));
KASSERT(!mapping->diom_mapped);
- cookie = bus_space_mmap(mapping->diom_bst, mapping->diom_addr, offset,
+ cookie = bus_space_mmap(mapping->diom_bst, mapping->base, offset,
PROT_READ|PROT_WRITE,
BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE);
KASSERT(cookie != (paddr_t)-1);