[Intel-gfx] [PATCH 1/5] drm/i915: Allow i915 to manage the vma offset nodes instead of drm core

2019-10-23 Thread Abdiel Janulgue
Have i915 replace the core drm_gem_mmap implementation to overcome its
limitation in having only a single mmap offset node per gem object.
This change allows us to have multiple mmap offsets per object and
enables a mmapping instance to use unique fault-handlers per user vma.

This allows i915 to store extra data within vma->vm_private_data and
assign the pagefault ops for each mmap instance allowing objects to use
multiple fault handlers depending on its backing storage.

v2:
 - Fix race condition exposed by gem_mmap_gtt@close-race. Simplify
   lifetime management of the mmap offset objects be ensuring it is
   owned by the parent gem object instead of refcounting.
 - Track mmo used by fencing to Avoid locking when revoking mmaps
   during GPU reset.
 - Rebase.
v3:
- Simplify mmo tracking
v4:
- use vma->mmo in __i915_gem_object_release_mmap_gtt

Signed-off-by: Abdiel Janulgue 
Cc: Matthew Auld 
Cc: Joonas Lahtinen 
Cc: Chris Wilson 
---
 drivers/gpu/drm/i915/gem/i915_gem_domain.c|   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_mman.c  | 229 --
 drivers/gpu/drm/i915/gem/i915_gem_object.c|  13 +
 drivers/gpu/drm/i915/gem/i915_gem_object.h|   9 +-
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |  19 ++
 .../drm/i915/gem/selftests/i915_gem_mman.c|  12 +-
 drivers/gpu/drm/i915/gt/intel_reset.c |   7 +-
 drivers/gpu/drm/i915/i915_drv.c   |  10 +-
 drivers/gpu/drm/i915/i915_drv.h   |   3 +-
 drivers/gpu/drm/i915/i915_gem.c   |   2 +-
 drivers/gpu/drm/i915/i915_vma.c   |  15 +-
 drivers/gpu/drm/i915/i915_vma.h   |   3 +
 12 files changed, 274 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c 
b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
index 9937b4c341f1..40792d2017a7 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -254,7 +254,7 @@ int i915_gem_object_set_cache_level(struct 
drm_i915_gem_object *obj,
}
 
if (obj->userfault_count)
-   __i915_gem_object_release_mmap(obj);
+   __i915_gem_object_release_mmap_gtt(obj);
 
/*
 * As we no longer need a fence for GTT access,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c 
b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index fd4122d8c0a9..3491bb06606b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -219,7 +219,8 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
 {
 #define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT)
struct vm_area_struct *area = vmf->vma;
-   struct drm_i915_gem_object *obj = to_intel_bo(area->vm_private_data);
+   struct i915_mmap_offset *priv = area->vm_private_data;
+   struct drm_i915_gem_object *obj = priv->obj;
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *i915 = to_i915(dev);
struct intel_runtime_pm *rpm = &i915->runtime_pm;
@@ -312,6 +313,9 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
list_add(&obj->userfault_link, &i915->ggtt.userfault_list);
mutex_unlock(&i915->ggtt.vm.mutex);
 
+   /* Track the mmo associated with the fenced vma */
+   vma->mmo = priv;
+
if (CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)
intel_wakeref_auto(&i915->ggtt.userfault_wakeref,
   
msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND));
@@ -358,7 +362,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
}
 }
 
-void __i915_gem_object_release_mmap(struct drm_i915_gem_object *obj)
+void __i915_gem_object_release_mmap_gtt(struct drm_i915_gem_object *obj)
 {
struct i915_vma *vma;
 
@@ -366,20 +370,16 @@ void __i915_gem_object_release_mmap(struct 
drm_i915_gem_object *obj)
 
obj->userfault_count = 0;
list_del(&obj->userfault_link);
-   drm_vma_node_unmap(&obj->base.vma_node,
-  obj->base.dev->anon_inode->i_mapping);
 
-   for_each_ggtt_vma(vma, obj)
+   for_each_ggtt_vma(vma, obj) {
+   if (vma->mmo)
+   drm_vma_node_unmap(&vma->mmo->vma_node,
+  
obj->base.dev->anon_inode->i_mapping);
i915_vma_unset_userfault(vma);
+   }
 }
 
 /**
- * i915_gem_object_release_mmap - remove physical page mappings
- * @obj: obj in question
- *
- * Preserve the reservation of the mmapping with the DRM core code, but
- * relinquish ownership of the pages back to the system.
- *
  * It is vital that we remove the page mapping if we have mapped a tiled
  * object through the GTT and then lose the fence register due to
  * resource pressure. Similarly if the object has been moved out of the
@@ -387,7 +387,7 @@ void __i915_gem_object_release_mmap(struct 
drm_i915_gem_object *obj)
  * mappin

[Intel-gfx] [PATCH 1/5] drm/i915: Allow i915 to manage the vma offset nodes instead of drm core

2019-10-23 Thread Abdiel Janulgue
Have i915 replace the core drm_gem_mmap implementation to overcome its
limitation in having only a single mmap offset node per gem object.
This change allows us to have multiple mmap offsets per object and
enables a mmapping instance to use unique fault-handlers per user vma.

This allows i915 to store extra data within vma->vm_private_data and
assign the pagefault ops for each mmap instance allowing objects to use
multiple fault handlers depending on its backing storage.

v2:
 - Fix race condition exposed by gem_mmap_gtt@close-race. Simplify
   lifetime management of the mmap offset objects be ensuring it is
   owned by the parent gem object instead of refcounting.
 - Track mmo used by fencing to avoid locking when revoking mmaps
   during GPU reset.
 - Rebase.
v3:
- Simplify mmo tracking
v4:
- use vma->mmo in __i915_gem_object_release_mmap_gtt

Signed-off-by: Abdiel Janulgue 
Cc: Matthew Auld 
Cc: Joonas Lahtinen 
Cc: Chris Wilson 
---
 drivers/gpu/drm/i915/gem/i915_gem_domain.c|   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_mman.c  | 229 --
 drivers/gpu/drm/i915/gem/i915_gem_object.c|  13 +
 drivers/gpu/drm/i915/gem/i915_gem_object.h|   9 +-
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |  19 ++
 .../drm/i915/gem/selftests/i915_gem_mman.c|  12 +-
 drivers/gpu/drm/i915/gt/intel_reset.c |   7 +-
 drivers/gpu/drm/i915/i915_drv.c   |  10 +-
 drivers/gpu/drm/i915/i915_drv.h   |   3 +-
 drivers/gpu/drm/i915/i915_gem.c   |   2 +-
 drivers/gpu/drm/i915/i915_vma.c   |  15 +-
 drivers/gpu/drm/i915/i915_vma.h   |   3 +
 12 files changed, 274 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c 
b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
index 9937b4c341f1..40792d2017a7 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -254,7 +254,7 @@ int i915_gem_object_set_cache_level(struct 
drm_i915_gem_object *obj,
}
 
if (obj->userfault_count)
-   __i915_gem_object_release_mmap(obj);
+   __i915_gem_object_release_mmap_gtt(obj);
 
/*
 * As we no longer need a fence for GTT access,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c 
b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index fd4122d8c0a9..3491bb06606b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -219,7 +219,8 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
 {
 #define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT)
struct vm_area_struct *area = vmf->vma;
-   struct drm_i915_gem_object *obj = to_intel_bo(area->vm_private_data);
+   struct i915_mmap_offset *priv = area->vm_private_data;
+   struct drm_i915_gem_object *obj = priv->obj;
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *i915 = to_i915(dev);
struct intel_runtime_pm *rpm = &i915->runtime_pm;
@@ -312,6 +313,9 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
list_add(&obj->userfault_link, &i915->ggtt.userfault_list);
mutex_unlock(&i915->ggtt.vm.mutex);
 
+   /* Track the mmo associated with the fenced vma */
+   vma->mmo = priv;
+
if (CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)
intel_wakeref_auto(&i915->ggtt.userfault_wakeref,
   
msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND));
@@ -358,7 +362,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
}
 }
 
-void __i915_gem_object_release_mmap(struct drm_i915_gem_object *obj)
+void __i915_gem_object_release_mmap_gtt(struct drm_i915_gem_object *obj)
 {
struct i915_vma *vma;
 
@@ -366,20 +370,16 @@ void __i915_gem_object_release_mmap(struct 
drm_i915_gem_object *obj)
 
obj->userfault_count = 0;
list_del(&obj->userfault_link);
-   drm_vma_node_unmap(&obj->base.vma_node,
-  obj->base.dev->anon_inode->i_mapping);
 
-   for_each_ggtt_vma(vma, obj)
+   for_each_ggtt_vma(vma, obj) {
+   if (vma->mmo)
+   drm_vma_node_unmap(&vma->mmo->vma_node,
+  
obj->base.dev->anon_inode->i_mapping);
i915_vma_unset_userfault(vma);
+   }
 }
 
 /**
- * i915_gem_object_release_mmap - remove physical page mappings
- * @obj: obj in question
- *
- * Preserve the reservation of the mmapping with the DRM core code, but
- * relinquish ownership of the pages back to the system.
- *
  * It is vital that we remove the page mapping if we have mapped a tiled
  * object through the GTT and then lose the fence register due to
  * resource pressure. Similarly if the object has been moved out of the
@@ -387,7 +387,7 @@ void __i915_gem_object_release_mmap(struct 
drm_i915_gem_object *obj)
  * mappin

[Intel-gfx] [PATCH 1/5] drm/i915: Allow i915 to manage the vma offset nodes instead of drm core

2019-10-21 Thread Abdiel Janulgue
Have i915 replace the core drm_gem_mmap implementation to overcome its
limitation in having only a single mmap offset node per gem object.
This change allows us to have multiple mmap offsets per object and
enables a mmapping instance to use unique fault-handlers per user vma.

This allows i915 to store extra data within vma->vm_private_data and
assign the pagefault ops for each mmap instance allowing objects to use
multiple fault handlers depending on its backing storage.

v2:
 - Fix race condition exposed by gem_mmap_gtt@close-race. Simplify
   lifetime management of the mmap offset objects be ensuring it is
   owned by the parent gem object instead of refcounting.
 - Track mmo used by fencing to Avoid locking when revoking mmaps
   during GPU reset.
 - Rebase.
v3:
- Simplify mmo tracking
v4:
- use vma->mmo in __i915_gem_object_release_mmap_gtt

Signed-off-by: Abdiel Janulgue 
Cc: Matthew Auld 
Cc: Joonas Lahtinen 
Cc: Chris Wilson 
---
 drivers/gpu/drm/i915/gem/i915_gem_domain.c|   2 +-
 drivers/gpu/drm/i915/gem/i915_gem_mman.c  | 229 --
 drivers/gpu/drm/i915/gem/i915_gem_object.c|  13 +
 drivers/gpu/drm/i915/gem/i915_gem_object.h|   9 +-
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |  19 ++
 .../drm/i915/gem/selftests/i915_gem_mman.c|  12 +-
 drivers/gpu/drm/i915/gt/intel_reset.c |   7 +-
 drivers/gpu/drm/i915/i915_drv.c   |  10 +-
 drivers/gpu/drm/i915/i915_drv.h   |   3 +-
 drivers/gpu/drm/i915/i915_gem.c   |   2 +-
 drivers/gpu/drm/i915/i915_vma.c   |  15 +-
 drivers/gpu/drm/i915/i915_vma.h   |   4 +
 12 files changed, 275 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c 
b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
index 9937b4c341f1..40792d2017a7 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -254,7 +254,7 @@ int i915_gem_object_set_cache_level(struct 
drm_i915_gem_object *obj,
}
 
if (obj->userfault_count)
-   __i915_gem_object_release_mmap(obj);
+   __i915_gem_object_release_mmap_gtt(obj);
 
/*
 * As we no longer need a fence for GTT access,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c 
b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index fd4122d8c0a9..3491bb06606b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -219,7 +219,8 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
 {
 #define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT)
struct vm_area_struct *area = vmf->vma;
-   struct drm_i915_gem_object *obj = to_intel_bo(area->vm_private_data);
+   struct i915_mmap_offset *priv = area->vm_private_data;
+   struct drm_i915_gem_object *obj = priv->obj;
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *i915 = to_i915(dev);
struct intel_runtime_pm *rpm = &i915->runtime_pm;
@@ -312,6 +313,9 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
list_add(&obj->userfault_link, &i915->ggtt.userfault_list);
mutex_unlock(&i915->ggtt.vm.mutex);
 
+   /* Track the mmo associated with the fenced vma */
+   vma->mmo = priv;
+
if (CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)
intel_wakeref_auto(&i915->ggtt.userfault_wakeref,
   
msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND));
@@ -358,7 +362,7 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
}
 }
 
-void __i915_gem_object_release_mmap(struct drm_i915_gem_object *obj)
+void __i915_gem_object_release_mmap_gtt(struct drm_i915_gem_object *obj)
 {
struct i915_vma *vma;
 
@@ -366,20 +370,16 @@ void __i915_gem_object_release_mmap(struct 
drm_i915_gem_object *obj)
 
obj->userfault_count = 0;
list_del(&obj->userfault_link);
-   drm_vma_node_unmap(&obj->base.vma_node,
-  obj->base.dev->anon_inode->i_mapping);
 
-   for_each_ggtt_vma(vma, obj)
+   for_each_ggtt_vma(vma, obj) {
+   if (vma->mmo)
+   drm_vma_node_unmap(&vma->mmo->vma_node,
+  
obj->base.dev->anon_inode->i_mapping);
i915_vma_unset_userfault(vma);
+   }
 }
 
 /**
- * i915_gem_object_release_mmap - remove physical page mappings
- * @obj: obj in question
- *
- * Preserve the reservation of the mmapping with the DRM core code, but
- * relinquish ownership of the pages back to the system.
- *
  * It is vital that we remove the page mapping if we have mapped a tiled
  * object through the GTT and then lose the fence register due to
  * resource pressure. Similarly if the object has been moved out of the
@@ -387,7 +387,7 @@ void __i915_gem_object_release_mmap(struct 
drm_i915_gem_object *obj)
  * mappin

Re: [Intel-gfx] [PATCH 1/5] drm/i915: Allow i915 to manage the vma offset nodes instead of drm core

2019-09-04 Thread Daniel Vetter
On Mon, Aug 26, 2019 at 2:21 PM Abdiel Janulgue
 wrote:
>
> Have i915 replace the core drm_gem_mmap implementation to overcome its
> limitation in having only a single mmap offset node per gem object.
> The change allows us to have multiple mmap offsets per object. This
> enables a mmapping instance to use unique fault-handlers per user vma.
>
> This enables us to store extra data within vma->vm_private_data and assign
> the pagefault ops for each mmap instance allowing objects to use multiple
> fault handlers depending on its backing storage.
>
> Signed-off-by: Abdiel Janulgue 
> Cc: Joonas Lahtinen 
> Cc: Chris Wilson 
> ---
>  drivers/gpu/drm/i915/gem/i915_gem_mman.c  | 193 --
>  drivers/gpu/drm/i915/gem/i915_gem_object.c|  19 ++
>  drivers/gpu/drm/i915/gem/i915_gem_object.h|   7 +-
>  .../gpu/drm/i915/gem/i915_gem_object_types.h  |  18 ++
>  .../drm/i915/gem/selftests/i915_gem_mman.c|  12 +-
>  drivers/gpu/drm/i915/gt/intel_reset.c |  11 +-
>  drivers/gpu/drm/i915/i915_drv.c   |   9 +-
>  drivers/gpu/drm/i915/i915_drv.h   |   1 +
>  drivers/gpu/drm/i915/i915_vma.c   |  20 +-
>  9 files changed, 254 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c 
> b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
> index 595539a09e38..fb7e39f115d7 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
> @@ -218,7 +218,8 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
>  {
>  #define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT)
> struct vm_area_struct *area = vmf->vma;
> -   struct drm_i915_gem_object *obj = to_intel_bo(area->vm_private_data);
> +   struct i915_mmap_offset *priv = area->vm_private_data;
> +   struct drm_i915_gem_object *obj = priv->obj;
> struct drm_device *dev = obj->base.dev;
> struct drm_i915_private *i915 = to_i915(dev);
> struct intel_runtime_pm *rpm = &i915->runtime_pm;
> @@ -372,13 +373,20 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
>  void __i915_gem_object_release_mmap(struct drm_i915_gem_object *obj)
>  {
> struct i915_vma *vma;
> +   struct i915_mmap_offset *mmo;
>
> GEM_BUG_ON(!obj->userfault_count);
>
> obj->userfault_count = 0;
> list_del(&obj->userfault_link);
> -   drm_vma_node_unmap(&obj->base.vma_node,
> -  obj->base.dev->anon_inode->i_mapping);
> +
> +   mutex_lock(&obj->mmo_lock);
> +   list_for_each_entry(mmo, &obj->mmap_offsets, offset) {
> +   if (mmo->mmap_type == I915_MMAP_TYPE_GTT)
> +   drm_vma_node_unmap(&mmo->vma_node,
> +  
> obj->base.dev->anon_inode->i_mapping);
> +   }
> +   mutex_unlock(&obj->mmo_lock);
>
> for_each_ggtt_vma(vma, obj)
> i915_vma_unset_userfault(vma);
> @@ -433,14 +441,33 @@ void i915_gem_object_release_mmap(struct 
> drm_i915_gem_object *obj)
> intel_runtime_pm_put(&i915->runtime_pm, wakeref);
>  }
>
> -static int create_mmap_offset(struct drm_i915_gem_object *obj)
> +static void init_mmap_offset(struct drm_i915_gem_object *obj,
> +struct i915_mmap_offset *mmo)
> +{
> +   mutex_lock(&obj->mmo_lock);
> +   kref_init(&mmo->ref);
> +   list_add(&mmo->offset, &obj->mmap_offsets);
> +   mutex_unlock(&obj->mmo_lock);
> +
> +   mmo->obj = obj;
> +}
> +
> +static int create_mmap_offset(struct drm_i915_gem_object *obj,
> + struct i915_mmap_offset *mmo)
>  {
> struct drm_i915_private *i915 = to_i915(obj->base.dev);
> +   struct drm_device *dev = obj->base.dev;
> int err;
>
> -   err = drm_gem_create_mmap_offset(&obj->base);
> -   if (likely(!err))
> +   drm_vma_node_reset(&mmo->vma_node);
> +   if (mmo->file)
> +   drm_vma_node_allow(&mmo->vma_node, mmo->file);
> +   err = drm_vma_offset_add(dev->vma_offset_manager, &mmo->vma_node,
> +obj->base.size / PAGE_SIZE);
> +   if (likely(!err)) {
> +   init_mmap_offset(obj, mmo);
> return 0;
> +   }
>
> /* Attempt to reap some mmap space from dead objects */
> do {
> @@ -451,32 +478,48 @@ static int create_mmap_offset(struct 
> drm_i915_gem_object *obj)
> break;
>
> i915_gem_drain_freed_objects(i915);
> -   err = drm_gem_create_mmap_offset(&obj->base);
> -   if (!err)
> +   err = drm_vma_offset_add(dev->vma_offset_manager, 
> &mmo->vma_node,
> +obj->base.size / PAGE_SIZE);
> +   if (!err) {
> +   init_mmap_offset(obj, mmo);
> break;
> +   }
>
> } while (flush_delayed_work(&i915->gem.retire_work));
>
> return err;
>  }
>
> -int
> -i9

Re: [Intel-gfx] [PATCH 1/5] drm/i915: Allow i915 to manage the vma offset nodes instead of drm core

2019-08-26 Thread Chris Wilson
Quoting Abdiel Janulgue (2019-08-26 13:20:58)
> @@ -641,10 +642,18 @@ static void revoke_mmaps(struct intel_gt *gt)
> GEM_BUG_ON(vma->fence != >->ggtt->fence_regs[i]);
> node = &vma->obj->base.vma_node;
> vma_offset = vma->ggtt_view.partial.offset << PAGE_SHIFT;
> -   unmap_mapping_range(gt->i915->drm.anon_inode->i_mapping,
> +
> +   list_for_each_entry(mmo, &vma->obj->mmap_offsets, offset) {
> +   node = &mmo->vma_node;
> +   if (!drm_mm_node_allocated(&node->vm_node) ||
> +   mmo->mmap_type != I915_MMAP_TYPE_GTT)
> +   continue;

That list needs locking as is not protected by the reset srcu (and you
are not allowed your own locking in here, unless you have a jolly good
reason and can prove it will never block a reset).

One thing to observe is is that you only ever need the mmo associated
with a fence for revocation upon reset, and you could use a local list
for tracking the active mmo.
-Chris
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Re: [Intel-gfx] [PATCH 1/5] drm/i915: Allow i915 to manage the vma offset nodes instead of drm core

2019-08-26 Thread Chris Wilson
Quoting Abdiel Janulgue (2019-08-26 13:20:58)
> -static int create_mmap_offset(struct drm_i915_gem_object *obj)
> +static void init_mmap_offset(struct drm_i915_gem_object *obj,
> +struct i915_mmap_offset *mmo)
> +{
> +   mutex_lock(&obj->mmo_lock);

This lock should only be guarding obj->mmap_offsets. You don't need to
take it around every kref, just be careful to remove the link on close.

> +   kref_init(&mmo->ref);
> +   list_add(&mmo->offset, &obj->mmap_offsets);
> +   mutex_unlock(&obj->mmo_lock);
> +
> +   mmo->obj = obj;
> +}

> +/* This overcomes the limitation in drm_gem_mmap's assignment of a
> + * drm_gem_object as the vma->vm_private_data. Since we need to
> + * be able to resolve multiple mmap offsets which could be tied
> + * to a single gem object.
> + */
> +int i915_gem_mmap(struct file *filp, struct vm_area_struct *vma)
> +{
> +   struct drm_vma_offset_node *node;
> +   struct drm_file *priv = filp->private_data;
> +   struct drm_device *dev = priv->minor->dev;
> +   struct i915_mmap_offset *mmo = NULL;
> +   struct drm_gem_object *obj = NULL;
> +
> +   if (drm_dev_is_unplugged(dev))
> +   return -ENODEV;
> +
> +   drm_vma_offset_lock_lookup(dev->vma_offset_manager);
> +   node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
> + vma->vm_pgoff,
> + vma_pages(vma));
> +   if (likely(node)) {
> +   mmo = container_of(node, struct i915_mmap_offset,
> +  vma_node);
> +   /*
> +* Skip 0-refcnted objects as it is in the process of being
> +* destroyed and will be invalid when the vma manager lock
> +* is released.
> +*/
> +   obj = &mmo->obj->base;
> +   if (!kref_get_unless_zero(&obj->refcount))
> +   obj = NULL;

Hmm, references are still weird. This doesn't seem like it protects
against

Thread AThread B
  mmap(fd, offset_of_A);  gem_close(fd, A);


Time for a gem_mmap_gtt/close-race.
-Chris
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

[Intel-gfx] [PATCH 1/5] drm/i915: Allow i915 to manage the vma offset nodes instead of drm core

2019-08-26 Thread Abdiel Janulgue
Have i915 replace the core drm_gem_mmap implementation to overcome its
limitation in having only a single mmap offset node per gem object.
The change allows us to have multiple mmap offsets per object. This
enables a mmapping instance to use unique fault-handlers per user vma.

This enables us to store extra data within vma->vm_private_data and assign
the pagefault ops for each mmap instance allowing objects to use multiple
fault handlers depending on its backing storage.

Signed-off-by: Abdiel Janulgue 
Cc: Joonas Lahtinen 
Cc: Chris Wilson 
---
 drivers/gpu/drm/i915/gem/i915_gem_mman.c  | 193 --
 drivers/gpu/drm/i915/gem/i915_gem_object.c|  19 ++
 drivers/gpu/drm/i915/gem/i915_gem_object.h|   7 +-
 .../gpu/drm/i915/gem/i915_gem_object_types.h  |  18 ++
 .../drm/i915/gem/selftests/i915_gem_mman.c|  12 +-
 drivers/gpu/drm/i915/gt/intel_reset.c |  11 +-
 drivers/gpu/drm/i915/i915_drv.c   |   9 +-
 drivers/gpu/drm/i915/i915_drv.h   |   1 +
 drivers/gpu/drm/i915/i915_vma.c   |  20 +-
 9 files changed, 254 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c 
b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index 595539a09e38..fb7e39f115d7 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -218,7 +218,8 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
 {
 #define MIN_CHUNK_PAGES (SZ_1M >> PAGE_SHIFT)
struct vm_area_struct *area = vmf->vma;
-   struct drm_i915_gem_object *obj = to_intel_bo(area->vm_private_data);
+   struct i915_mmap_offset *priv = area->vm_private_data;
+   struct drm_i915_gem_object *obj = priv->obj;
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *i915 = to_i915(dev);
struct intel_runtime_pm *rpm = &i915->runtime_pm;
@@ -372,13 +373,20 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
 void __i915_gem_object_release_mmap(struct drm_i915_gem_object *obj)
 {
struct i915_vma *vma;
+   struct i915_mmap_offset *mmo;
 
GEM_BUG_ON(!obj->userfault_count);
 
obj->userfault_count = 0;
list_del(&obj->userfault_link);
-   drm_vma_node_unmap(&obj->base.vma_node,
-  obj->base.dev->anon_inode->i_mapping);
+
+   mutex_lock(&obj->mmo_lock);
+   list_for_each_entry(mmo, &obj->mmap_offsets, offset) {
+   if (mmo->mmap_type == I915_MMAP_TYPE_GTT)
+   drm_vma_node_unmap(&mmo->vma_node,
+  
obj->base.dev->anon_inode->i_mapping);
+   }
+   mutex_unlock(&obj->mmo_lock);
 
for_each_ggtt_vma(vma, obj)
i915_vma_unset_userfault(vma);
@@ -433,14 +441,33 @@ void i915_gem_object_release_mmap(struct 
drm_i915_gem_object *obj)
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 }
 
-static int create_mmap_offset(struct drm_i915_gem_object *obj)
+static void init_mmap_offset(struct drm_i915_gem_object *obj,
+struct i915_mmap_offset *mmo)
+{
+   mutex_lock(&obj->mmo_lock);
+   kref_init(&mmo->ref);
+   list_add(&mmo->offset, &obj->mmap_offsets);
+   mutex_unlock(&obj->mmo_lock);
+
+   mmo->obj = obj;
+}
+
+static int create_mmap_offset(struct drm_i915_gem_object *obj,
+ struct i915_mmap_offset *mmo)
 {
struct drm_i915_private *i915 = to_i915(obj->base.dev);
+   struct drm_device *dev = obj->base.dev;
int err;
 
-   err = drm_gem_create_mmap_offset(&obj->base);
-   if (likely(!err))
+   drm_vma_node_reset(&mmo->vma_node);
+   if (mmo->file)
+   drm_vma_node_allow(&mmo->vma_node, mmo->file);
+   err = drm_vma_offset_add(dev->vma_offset_manager, &mmo->vma_node,
+obj->base.size / PAGE_SIZE);
+   if (likely(!err)) {
+   init_mmap_offset(obj, mmo);
return 0;
+   }
 
/* Attempt to reap some mmap space from dead objects */
do {
@@ -451,32 +478,48 @@ static int create_mmap_offset(struct drm_i915_gem_object 
*obj)
break;
 
i915_gem_drain_freed_objects(i915);
-   err = drm_gem_create_mmap_offset(&obj->base);
-   if (!err)
+   err = drm_vma_offset_add(dev->vma_offset_manager, 
&mmo->vma_node,
+obj->base.size / PAGE_SIZE);
+   if (!err) {
+   init_mmap_offset(obj, mmo);
break;
+   }
 
} while (flush_delayed_work(&i915->gem.retire_work));
 
return err;
 }
 
-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,
+ e