On Tue, Oct 11, 2022 at 06:41:23PM +0100, Matthew Auld wrote:
On 11/10/2022 17:27, Matthew Auld wrote:
On 10/10/2022 07:58, Niranjana Vishwanathapura wrote:
Each VM creates a root_obj and shares it with all of its private objects
to use it as dma_resv object. This has a performance advantage as it
requires a single dma_resv object update for all private BOs vs list of
dma_resv objects update for shared BOs, in the execbuf path.

VM private BOs can be only mapped on specified VM and cannot be dmabuf
exported. Also, they are supported only in vm_bind mode.

v2: Pad struct drm_i915_gem_create_ext_vm_private for 64bit alignment,
     add input validity checks.
v3: Create root_obj only for ppgtt.

Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathap...@intel.com>
Signed-off-by: Andi Shyti <andi.sh...@linux.intel.com>
---
  drivers/gpu/drm/i915/gem/i915_gem_context.c   | 16 +++++-
  drivers/gpu/drm/i915/gem/i915_gem_create.c    | 49 ++++++++++++++++++-
  drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c    |  6 +++
  .../gpu/drm/i915/gem/i915_gem_execbuffer.c    |  4 ++
  drivers/gpu/drm/i915/gem/i915_gem_object.c    |  3 ++
  .../gpu/drm/i915/gem/i915_gem_object_types.h  |  3 ++
  drivers/gpu/drm/i915/gem/i915_gem_ttm.c       |  3 ++
  .../drm/i915/gem/i915_gem_vm_bind_object.c    |  9 ++++
  drivers/gpu/drm/i915/gt/intel_gtt.c           |  3 ++
  drivers/gpu/drm/i915/gt/intel_gtt.h           |  2 +
  drivers/gpu/drm/i915/i915_vma.c               |  1 +
  drivers/gpu/drm/i915/i915_vma_types.h         |  2 +
  include/uapi/drm/i915_drm.h                   | 33 +++++++++++++
  13 files changed, 131 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 793345cbf99e..5ea7064805f3 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -83,6 +83,7 @@
  #include "i915_file_private.h"
  #include "i915_gem_context.h"
+#include "i915_gem_internal.h"
  #include "i915_trace.h"
  #include "i915_user_extensions.h"
@@ -1795,6 +1796,7 @@ int i915_gem_vm_create_ioctl(struct drm_device *dev, void *data,
      struct drm_i915_private *i915 = to_i915(dev);
      struct drm_i915_gem_vm_control *args = data;
      struct drm_i915_file_private *file_priv = file->driver_priv;
+    struct drm_i915_gem_object *obj;
      struct i915_ppgtt *ppgtt;
      u32 id;
      int err;
@@ -1817,15 +1819,27 @@ int i915_gem_vm_create_ioctl(struct drm_device *dev, void *data,
              goto err_put;
      }
+    obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
+    if (IS_ERR(obj)) {
+        err = PTR_ERR(obj);
+        goto err_put;
+    }
+
+    ppgtt->vm.root_obj = obj;
+    ppgtt->vm.vm_bind_mode = true;

Won't this temporarily break execbuf2? Only in the final patch does this depend on the new flag? Perhaps the patch split could be improved, or maybe we can just keep this as false here, until the final patch? Could also maybe also keep root_obj = NULL, until the last patch also?

Yah, it was expected to be set in the final patch.
Ok, will move creating the root_obj part also to final patch.
Also, will remove vm.vm_bind_mode flag altogether. Instead the
'vm.root_obj != NULL' check will tell if VM is in vm_bind mode.


+
      err = xa_alloc(&file_priv->vm_xa, &id, &ppgtt->vm,
                 xa_limit_32b, GFP_KERNEL);
      if (err)
-        goto err_put;
+        goto err_root_obj_put;
      GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */
      args->vm_id = id;
      return 0;
+err_root_obj_put:
+    if (ppgtt->vm.root_obj)
+        i915_gem_object_put(ppgtt->vm.root_obj);
  err_put:
      i915_vm_put(&ppgtt->vm);
      return err;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_create.c b/drivers/gpu/drm/i915/gem/i915_gem_create.c
index 5c6e396ab74d..694d4638ac8b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_create.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_create.c
@@ -11,6 +11,7 @@
  #include "pxp/intel_pxp.h"
  #include "i915_drv.h"
+#include "i915_gem_context.h"
  #include "i915_gem_create.h"
  #include "i915_trace.h"
  #include "i915_user_extensions.h"
@@ -251,6 +252,7 @@ struct create_ext {
      unsigned int n_placements;
      unsigned int placement_mask;
      unsigned long flags;
+    u32 vm_id;
  };
  static void repr_placements(char *buf, size_t size,
@@ -400,9 +402,32 @@ static int ext_set_protected(struct i915_user_extension __user *base, void *data
      return 0;
  }
+static int ext_set_vm_private(struct i915_user_extension __user *base,
+                  void *data)
+{
+    struct drm_i915_gem_create_ext_vm_private ext;
+    struct create_ext *ext_data = data;
+
+    if (copy_from_user(&ext, base, sizeof(ext)))
+        return -EFAULT;
+
+    /* Reserved fields must be 0 */
+    if (ext.rsvd)
+        return -EINVAL;
+
+    /* vm_id 0 is reserved */
+    if (!ext.vm_id)
+        return -ENOENT;
+
+    ext_data->vm_id = ext.vm_id;
+
+    return 0;
+}
+
  static const i915_user_extension_fn create_extensions[] = {
      [I915_GEM_CREATE_EXT_MEMORY_REGIONS] = ext_set_placements,
      [I915_GEM_CREATE_EXT_PROTECTED_CONTENT] = ext_set_protected,
+    [I915_GEM_CREATE_EXT_VM_PRIVATE] = ext_set_vm_private,
  };
  /**
@@ -418,6 +443,7 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data,
      struct drm_i915_private *i915 = to_i915(dev);
      struct drm_i915_gem_create_ext *args = data;
      struct create_ext ext_data = { .i915 = i915 };
+    struct i915_address_space *vm = NULL;
      struct drm_i915_gem_object *obj;
      int ret;
@@ -431,6 +457,12 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data,
      if (ret)
          return ret;
+    if (ext_data.vm_id) {
+        vm = i915_gem_vm_lookup(file->driver_priv, ext_data.vm_id);
+        if (unlikely(!vm))
+            return -ENOENT;
+    }
+
      if (!ext_data.n_placements) {
          ext_data.placements[0] =
              intel_memory_region_by_type(i915, INTEL_MEMORY_SYSTEM);
@@ -457,8 +489,21 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data,
                          ext_data.placements,
                          ext_data.n_placements,
                          ext_data.flags);
-    if (IS_ERR(obj))
-        return PTR_ERR(obj);
+    if (IS_ERR(obj)) {
+        ret = PTR_ERR(obj);
+        goto vm_put;
+    }
+
+    if (vm) {
+        obj->base.resv = vm->root_obj->base.resv;
+        obj->priv_root = i915_gem_object_get(vm->root_obj);
+        i915_vm_put(vm);
+    }
      return i915_gem_publish(obj, file, &args->size, &args->handle);
+vm_put:
+    if (vm)
+        i915_vm_put(vm);
+
+    return ret;
  }
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index f5062d0c6333..6433173c3e84 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -218,6 +218,12 @@ struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags)
      struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
      DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+    if (obj->priv_root) {
+        drm_dbg(obj->base.dev,
+            "Exporting VM private objects is not allowed\n");
+        return ERR_PTR(-EINVAL);
+    }
+
      exp_info.ops = &i915_dmabuf_ops;
      exp_info.size = gem_obj->size;
      exp_info.flags = flags;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 9fb9f6faafd8..4673e0812277 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -864,6 +864,10 @@ static struct i915_vma *eb_lookup_vma(struct i915_execbuffer *eb, u32 handle)
          if (unlikely(!obj))
              return ERR_PTR(-ENOENT);
+        /* VM private objects are not supported here */
+        if (obj->priv_root)
+            return ERR_PTR(-EINVAL);
+
          /*
           * If the user has opted-in for protected-object tracking, make
           * sure the object encryption can be used.
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 62495d5d0038..b799c53ac4b1 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -108,6 +108,9 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
   */
  void __i915_gem_object_fini(struct drm_i915_gem_object *obj)
  {
+    if (obj->priv_root && !obj->ttm.created)
+        i915_gem_object_put(obj->priv_root);

Can we not ignore the ttm.created here? And then drop the object_put() below?


Ok, looks like __i915_gem_object_fini() is called for both
ttm and non-ttm objects.
So, will release the obj->priv_root here irrespective of
obj->ttm.created and will also move it below.

Otherwise,
Reviewed-by: Matthew Auld <matthew.a...@intel.com>


Thanks,
Niranjana


+
      mutex_destroy(&obj->mm.get_page.lock);
      mutex_destroy(&obj->mm.get_dma_page.lock);
      dma_resv_fini(&obj->base._resv);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
index d0d6772e6f36..b77bf0e07fe1 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -242,6 +242,9 @@ struct drm_i915_gem_object {
      const struct drm_i915_gem_object_ops *ops;
+    /* For VM private BO, points to root_obj in VM. NULL otherwise */
+    struct drm_i915_gem_object *priv_root;
+
      struct {
          /**
           * @vma.lock: protect the list/tree of vmas
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index d63f30efd631..233d670a91de 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -1200,6 +1200,9 @@ void i915_ttm_bo_destroy(struct ttm_buffer_object *bo)
      mutex_destroy(&obj->ttm.get_io_page.lock);
      if (obj->ttm.created) {
+        if (obj->priv_root)
+            i915_gem_object_put(obj->priv_root);
+

Reply via email to