From: Abdiel Janulgue <[email protected]>

CPU mmap implementation depending on the object's backing pages.
At the moment we introduce shmem and local-memory BAR fault handlers
Note that the mmap type is done one at a time to circumvent the DRM
offset manager limitation. Note that we multiplex mmap_gtt and
mmap_offset through the same ioctl, and use the zero extending behaviour
of drm to differentiate between them, when we inspect the flags.

Signed-off-by: Abdiel Janulgue <[email protected]>
Signed-off-by: Matthew Auld <[email protected]>
Cc: Joonas Lahtinen <[email protected]>
---
 drivers/gpu/drm/i915/i915_drv.c        |  5 +-
 drivers/gpu/drm/i915/i915_drv.h        |  3 +
 drivers/gpu/drm/i915/i915_gem.c        | 94 ++++++++++++++++++++++----
 drivers/gpu/drm/i915/i915_gem_object.h | 10 +++
 include/uapi/drm/i915_drm.h            | 30 ++++++++
 5 files changed, 126 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b1200d7ebd13..90785030a0dd 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -423,6 +423,7 @@ static int i915_getparam_ioctl(struct drm_device *dev, void 
*data,
        case I915_PARAM_HAS_EXEC_CAPTURE:
        case I915_PARAM_HAS_EXEC_BATCH_FIRST:
        case I915_PARAM_HAS_EXEC_FENCE_ARRAY:
+       case I915_PARAM_MMAP_OFFSET_VERSION:
                /* For the time being all of these are always true;
                 * if some supported hardware does not have one of these
                 * features this value needs to be provided from
@@ -2936,7 +2937,7 @@ const struct dev_pm_ops i915_pm_ops = {
 static const struct vm_operations_struct i915_gem_vm_ops = {
        .fault = i915_gem_fault,
        .open = drm_gem_vm_open,
-       .close = drm_gem_vm_close,
+       .close = i915_gem_close,
 };
 
 static const struct file_operations i915_driver_fops = {
@@ -2991,7 +2992,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
        DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, 
DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 
DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 
DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_OFFSET, i915_gem_mmap_gtt_ioctl, 
DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 
DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 
DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling_ioctl, 
DRM_RENDER_ALLOW),
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 065953a9264f..c6ae157d0ede 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2770,6 +2770,8 @@ int i915_gem_mmap_ioctl(struct drm_device *dev, void 
*data,
                        struct drm_file *file_priv);
 int i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file_priv);
+int i915_gem_mmap_offset_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file_priv);
 int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
                              struct drm_file *file_priv);
 int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
@@ -3073,6 +3075,7 @@ void i915_gem_suspend_late(struct drm_i915_private 
*dev_priv);
 void i915_gem_resume(struct drm_i915_private *dev_priv);
 int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma);
 vm_fault_t i915_gem_fault(struct vm_fault *vmf);
+void i915_gem_close(struct vm_area_struct *vma);
 int i915_gem_object_wait(struct drm_i915_gem_object *obj,
                         unsigned int flags,
                         long timeout);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 48dbb57fbc6d..cc6c88ec749d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2123,11 +2123,12 @@ static void i915_gem_object_free_mmap_offset(struct 
drm_i915_gem_object *obj)
        drm_gem_free_mmap_offset(&obj->base);
 }
 
-int
-i915_gem_mmap_gtt(struct drm_file *file,
-                 struct drm_device *dev,
-                 u32 handle,
-                 u64 *offset)
+static int
+__assign_gem_object_mmap_data(struct drm_file *file,
+                             u32 handle,
+                             enum i915_cpu_mmap_origin_type mmap_type,
+                             u64 mmap_flags,
+                             u64 *offset)
 {
        struct drm_i915_gem_object *obj;
        int ret;
@@ -2136,14 +2137,35 @@ i915_gem_mmap_gtt(struct drm_file *file,
        if (!obj)
                return -ENOENT;
 
+       if (atomic_read(&obj->mmap_count) &&
+           obj->mmap_origin != mmap_type) {
+               /* Re-map object with existing different map-type */
+               ret = -EINVAL;
+               goto err;
+       }
+
        ret = i915_gem_object_create_mmap_offset(obj);
-       if (ret == 0)
+       if (ret == 0) {
+               obj->mmap_origin = mmap_type;
+               obj->mmap_flags = mmap_flags;
                *offset = drm_vma_node_offset_addr(&obj->base.vma_node);
+       }
 
+ err:
        i915_gem_object_put(obj);
        return ret;
 }
 
+int
+i915_gem_mmap_gtt(struct drm_file *file,
+                 struct drm_device *dev,
+                 u32 handle,
+                 u64 *offset)
+{
+       return __assign_gem_object_mmap_data(file, handle, I915_MMAP_ORIGIN_GTT,
+                                            0, offset);
+}
+
 /**
  * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
  * @dev: DRM device
@@ -2163,9 +2185,45 @@ int
 i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
                        struct drm_file *file)
 {
-       struct drm_i915_gem_mmap_gtt *args = data;
+       struct drm_i915_gem_mmap_offset *args = data;
+       struct drm_i915_private *i915 = to_i915(dev);
+
+       if (args->flags & I915_MMAP_OFFSET_FLAGS)
+               return i915_gem_mmap_offset_ioctl(dev, data, file);
+
+       if (!HAS_MAPPABLE_APERTURE(i915)) {
+               DRM_ERROR("No aperture, cannot mmap via legacy GTT\n");
+               return -ENODEV;
+       }
+
+       return __assign_gem_object_mmap_data(file, args->handle,
+                                            I915_MMAP_ORIGIN_GTT,
+                                            0, &args->offset);
+}
+
+int i915_gem_mmap_offset_ioctl(struct drm_device *dev, void *data,
+                              struct drm_file *file)
+{
+       struct drm_i915_gem_mmap_offset *args = data;
 
-       return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
+       if ((args->flags & (I915_MMAP_OFFSET_WC | I915_MMAP_OFFSET_WB)) &&
+           !boot_cpu_has(X86_FEATURE_PAT))
+               return -ENODEV;
+
+        return __assign_gem_object_mmap_data(file, args->handle,
+                                            I915_MMAP_ORIGIN_OFFSET,
+                                            args->flags,
+                                            &args->offset);
+}
+
+void i915_gem_close(struct vm_area_struct *vma)
+{
+       struct drm_gem_object *gem = vma->vm_private_data;
+       struct drm_i915_gem_object *obj = to_intel_bo(gem);
+
+       atomic_dec(&obj->mmap_count);
+
+       drm_gem_vm_close(vma);
 }
 
 int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
@@ -2178,12 +2236,19 @@ int i915_gem_mmap(struct file *filp, struct 
vm_area_struct *vma)
                return ret;
 
        obj = to_intel_bo(vma->vm_private_data);
-       if (obj->memory_region) {
-               if (obj->mmap_origin == I915_MMAP_ORIGIN_OFFSET) {
-                       vma->vm_flags &= ~VM_PFNMAP;
-                       vma->vm_flags |= VM_MIXEDMAP;
-               }
+       if (obj->mmap_origin == I915_MMAP_ORIGIN_OFFSET) {
+               vma->vm_flags &= ~VM_PFNMAP;
+               vma->vm_flags |= VM_MIXEDMAP;
+               if (obj->mmap_flags & I915_MMAP_OFFSET_WC)
+                       vma->vm_page_prot =
+                               
pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
+               else if (obj->mmap_flags & I915_MMAP_OFFSET_WB)
+                       vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+               else if (obj->mmap_flags & I915_MMAP_OFFSET_UC)
+                       vma->vm_page_prot =
+                               
pgprot_noncached(vm_get_page_prot(vma->vm_flags));
        }
+       atomic_inc(&obj->mmap_count);
 
        return ret;
 }
@@ -4228,7 +4293,8 @@ int i915_gem_vmf_fill_pages_cpu(struct 
drm_i915_gem_object *obj,
        vm_fault_t vmf_ret;
        pgoff_t pg_off = (vmf->address - area->vm_start) >> PAGE_SHIFT;
 
-       if (HAS_MAPPABLE_APERTURE(dev_priv))
+       if (HAS_MAPPABLE_APERTURE(dev_priv) &&
+           obj->mmap_origin == I915_MMAP_ORIGIN_GTT)
                return __vmf_fill_pages_gtt(obj, vmf, page_offset);
 
        page = i915_gem_object_get_page(obj, pg_off);
diff --git a/drivers/gpu/drm/i915/i915_gem_object.h 
b/drivers/gpu/drm/i915/i915_gem_object.h
index 5c6bbe6f5e84..b37ffe2e17b6 100644
--- a/drivers/gpu/drm/i915/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/i915_gem_object.h
@@ -86,6 +86,12 @@ struct drm_i915_gem_object_ops {
                              pgoff_t);
 };
 
+enum i915_cpu_mmap_origin_type {
+       I915_MMAP_ORIGIN_NONE = 0,
+       I915_MMAP_ORIGIN_GTT,
+       I915_MMAP_ORIGIN_OFFSET,
+};
+
 struct drm_i915_gem_object {
        struct drm_gem_object base;
 
@@ -157,6 +163,10 @@ struct drm_i915_gem_object {
        unsigned int userfault_count;
        struct list_head userfault_link;
 
+       enum i915_cpu_mmap_origin_type mmap_origin;
+       atomic_t mmap_count;
+       u64 mmap_flags;
+
        struct list_head batch_pool_link;
        I915_SELFTEST_DECLARE(struct list_head st_link);
 
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 397810fa2d33..26d2274b5d2b 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -319,6 +319,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_PERF_ADD_CONFIG       0x37
 #define DRM_I915_PERF_REMOVE_CONFIG    0x38
 #define DRM_I915_QUERY                 0x39
+#define DRM_I915_GEM_MMAP_OFFSET       DRM_I915_GEM_MMAP_GTT
 
 #define DRM_IOCTL_I915_INIT            DRM_IOW( DRM_COMMAND_BASE + 
DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH           DRM_IO ( DRM_COMMAND_BASE + 
DRM_I915_FLUSH)
@@ -377,6 +378,7 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + 
DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
 #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG      DRM_IOW(DRM_COMMAND_BASE + 
DRM_I915_PERF_REMOVE_CONFIG, __u64)
 #define DRM_IOCTL_I915_QUERY                   DRM_IOWR(DRM_COMMAND_BASE + 
DRM_I915_QUERY, struct drm_i915_query)
+#define DRM_IOCTL_I915_GEM_MMAP_OFFSET         DRM_IOWR(DRM_COMMAND_BASE + 
DRM_I915_GEM_MMAP_OFFSET, struct drm_i915_gem_mmap_offset)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -559,6 +561,9 @@ typedef struct drm_i915_irq_wait {
  */
 #define I915_PARAM_MMAP_GTT_COHERENT   52
 
+/* Mmap offset ioctl */
+#define I915_PARAM_MMAP_OFFSET_VERSION 55
+
 typedef struct drm_i915_getparam {
        __s32 param;
        /*
@@ -731,6 +736,31 @@ struct drm_i915_gem_mmap_gtt {
        __u64 offset;
 };
 
+struct drm_i915_gem_mmap_offset {
+       /** Handle for the object being mapped. */
+       __u32 handle;
+       __u32 pad;
+       /**
+        * Fake offset to use for subsequent mmap call
+        *
+        * This is a fixed-size type for 32/64 compatibility.
+        */
+       __u64 offset;
+
+       /**
+        * Flags for extended behaviour.
+        *
+        * It is mandatory that either one of the _WC/_WB flags
+        * should be passed here.
+        */
+       __u64 flags;
+#define I915_MMAP_OFFSET_WC (1 << 0)
+#define I915_MMAP_OFFSET_WB (1 << 1)
+#define I915_MMAP_OFFSET_UC (1 << 2)
+#define I915_MMAP_OFFSET_FLAGS \
+       (I915_MMAP_OFFSET_WC | I915_MMAP_OFFSET_WB | I915_MMAP_OFFSET_UC)
+};
+
 struct drm_i915_gem_set_domain {
        /** Handle for the object */
        __u32 handle;
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to