All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
@ 2022-03-23 16:08 Lucas Stach
  2022-03-23 16:08 ` [PATCH 2/4] drm/etnaviv: move MMU context ref/unref into map/unmap_gem Lucas Stach
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Lucas Stach @ 2022-03-23 16:08 UTC (permalink / raw)
  To: etnaviv; +Cc: patchwork-lst, kernel, dri-devel, Russell King

When the mapping is already reaped the unmap must be a no-op, as we
would otherwise try to remove the mapping twice, corrupting the involved
data structures.

Cc: stable@vger.kernel.org # 5.4
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index 9fb1a2aadbcb..aabb997a74eb 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -286,6 +286,12 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
 
 	mutex_lock(&context->lock);
 
+	/* Bail if the mapping has been reaped by another thread */
+	if (!mapping->context) {
+		mutex_unlock(&context->lock);
+		return;
+	}
+
 	/* If the vram node is on the mm, unmap and remove the node */
 	if (mapping->vram_node.mm == &context->mm)
 		etnaviv_iommu_remove_mapping(context, mapping);
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/4] drm/etnaviv: move MMU context ref/unref into map/unmap_gem
  2022-03-23 16:08 [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem Lucas Stach
@ 2022-03-23 16:08 ` Lucas Stach
  2022-03-24 15:39   ` Philipp Zabel
  2022-03-23 16:08 ` [PATCH 3/4] drm/etnaviv: move flush_seq increment into etnaviv_iommu_map/unmap Lucas Stach
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Lucas Stach @ 2022-03-23 16:08 UTC (permalink / raw)
  To: etnaviv; +Cc: patchwork-lst, kernel, dri-devel, Russell King

This makes it a little more clear that the mapping holds a reference
to the context once the buffer has been successfully mapped into that
context and simplifies the error handling a bit.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 drivers/gpu/drm/etnaviv/etnaviv_gem.c | 11 +++--------
 drivers/gpu/drm/etnaviv/etnaviv_mmu.c |  3 +++
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index d5314aa28ff7..a68e6a17505e 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -294,18 +294,15 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
 		list_del(&mapping->obj_node);
 	}
 
-	mapping->context = etnaviv_iommu_context_get(mmu_context);
 	mapping->use = 1;
 
 	ret = etnaviv_iommu_map_gem(mmu_context, etnaviv_obj,
 				    mmu_context->global->memory_base,
 				    mapping, va);
-	if (ret < 0) {
-		etnaviv_iommu_context_put(mmu_context);
+	if (ret < 0)
 		kfree(mapping);
-	} else {
+	else
 		list_add_tail(&mapping->obj_node, &etnaviv_obj->vram_list);
-	}
 
 out:
 	mutex_unlock(&etnaviv_obj->lock);
@@ -498,10 +495,8 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)
 
 		WARN_ON(mapping->use);
 
-		if (context) {
+		if (context)
 			etnaviv_iommu_unmap_gem(context, mapping);
-			etnaviv_iommu_context_put(context);
-		}
 
 		list_del(&mapping->obj_node);
 		kfree(mapping);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index aabb997a74eb..3957b9a752f5 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -245,6 +245,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
 		iova = sg_dma_address(sgt->sgl) - memory_base;
 		if (iova < 0x80000000 - sg_dma_len(sgt->sgl)) {
 			mapping->iova = iova;
+			mapping->context = etnaviv_iommu_context_get(context);
 			list_add_tail(&mapping->mmu_node, &context->mappings);
 			ret = 0;
 			goto unlock;
@@ -271,6 +272,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
 		goto unlock;
 	}
 
+	mapping->context = etnaviv_iommu_context_get(context);
 	list_add_tail(&mapping->mmu_node, &context->mappings);
 	context->flush_seq++;
 unlock:
@@ -299,6 +301,7 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
 	list_del(&mapping->mmu_node);
 	context->flush_seq++;
 	mutex_unlock(&context->lock);
+	etnaviv_iommu_context_put(context);
 }
 
 static void etnaviv_iommu_context_free(struct kref *kref)
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/4] drm/etnaviv: move flush_seq increment into etnaviv_iommu_map/unmap
  2022-03-23 16:08 [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem Lucas Stach
  2022-03-23 16:08 ` [PATCH 2/4] drm/etnaviv: move MMU context ref/unref into map/unmap_gem Lucas Stach
@ 2022-03-23 16:08 ` Lucas Stach
  2022-03-24 15:39   ` Philipp Zabel
  2022-03-23 16:08 ` [PATCH 4/4] drm/etnaviv: reap idle softpin mappings when necessary Lucas Stach
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Lucas Stach @ 2022-03-23 16:08 UTC (permalink / raw)
  To: etnaviv; +Cc: patchwork-lst, kernel, dri-devel, Russell King

The flush sequence is a marker that the page tables have been changed
and any affected TLBs need to be flushed. Move the flush_seq increment
a little further down the call stack to place it next to the actual
page table manipulation. Not functional change.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index 3957b9a752f5..d41295208102 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -92,6 +92,8 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova,
 		da += bytes;
 	}
 
+	context->flush_seq++;
+
 	return 0;
 
 fail:
@@ -117,6 +119,8 @@ static void etnaviv_iommu_unmap(struct etnaviv_iommu_context *context, u32 iova,
 
 		da += bytes;
 	}
+
+	context->flush_seq++;
 }
 
 static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu_context *context,
@@ -274,7 +278,6 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
 
 	mapping->context = etnaviv_iommu_context_get(context);
 	list_add_tail(&mapping->mmu_node, &context->mappings);
-	context->flush_seq++;
 unlock:
 	mutex_unlock(&context->lock);
 
@@ -299,7 +302,6 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
 		etnaviv_iommu_remove_mapping(context, mapping);
 
 	list_del(&mapping->mmu_node);
-	context->flush_seq++;
 	mutex_unlock(&context->lock);
 	etnaviv_iommu_context_put(context);
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/4] drm/etnaviv: reap idle softpin mappings when necessary
  2022-03-23 16:08 [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem Lucas Stach
  2022-03-23 16:08 ` [PATCH 2/4] drm/etnaviv: move MMU context ref/unref into map/unmap_gem Lucas Stach
  2022-03-23 16:08 ` [PATCH 3/4] drm/etnaviv: move flush_seq increment into etnaviv_iommu_map/unmap Lucas Stach
@ 2022-03-23 16:08 ` Lucas Stach
  2022-03-24 15:39 ` [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem Philipp Zabel
  2022-03-31 10:50 ` Guido Günther
  4 siblings, 0 replies; 8+ messages in thread
From: Lucas Stach @ 2022-03-23 16:08 UTC (permalink / raw)
  To: etnaviv; +Cc: patchwork-lst, kernel, dri-devel, Russell King

Right now the only point where softpin mappings get removed from the
MMU context is when the mapped GEM object is destroyed. However,
userspace might want to reuse that address space before the object
is destroyed, which is a valid usage, as long as all mapping in that
region of the address space are no longer used by any GPU jobs.

Implement reaping of idle MMU mappings that would otherwise
prevent the insertion of a softpin mapping.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Tested-by: Guido Günther <agx@sigxcpu.org>
Acked-by: Guido Günther <agx@sigxcpu.org>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
---
 drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 39 +++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index d41295208102..dc1aa738c4f1 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -223,8 +223,47 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
 static int etnaviv_iommu_insert_exact(struct etnaviv_iommu_context *context,
 		   struct drm_mm_node *node, size_t size, u64 va)
 {
+	struct etnaviv_vram_mapping *m, *n;
+	struct drm_mm_node *scan_node;
+	LIST_HEAD(scan_list);
+	int ret;
+
 	lockdep_assert_held(&context->lock);
 
+	ret = drm_mm_insert_node_in_range(&context->mm, node, size, 0, 0, va,
+					  va + size, DRM_MM_INSERT_LOWEST);
+	if (ret != -ENOSPC)
+		return ret;
+
+	/*
+	 * When we can't insert the node, due to a existing mapping blocking
+	 * the address space, there are two possible reasons:
+	 * 1. Userspace genuinely messed up and tried to reuse address space
+	 * before the last job using this VMA has finished executing.
+	 * 2. The existing buffer mappings are idle, but the buffers are not
+	 * destroyed yet (likely due to being referenced by another context) in
+	 * which case the mappings will not be cleaned up and we must reap them
+	 * here to make space for the new mapping.
+	 */
+
+	drm_mm_for_each_node_in_range(scan_node, &context->mm, va, va + size) {
+		m = container_of(scan_node, struct etnaviv_vram_mapping,
+				 vram_node);
+
+		if (m->use)
+			return -ENOSPC;
+
+		list_add(&m->scan_node, &scan_list);
+	}
+
+	list_for_each_entry_safe(m, n, &scan_list, scan_node) {
+		etnaviv_iommu_remove_mapping(context, m);
+		etnaviv_iommu_context_put(m->context);
+		m->context = NULL;
+		list_del_init(&m->mmu_node);
+		list_del_init(&m->scan_node);
+	}
+
 	return drm_mm_insert_node_in_range(&context->mm, node, size, 0, 0, va,
 					   va + size, DRM_MM_INSERT_LOWEST);
 }
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
  2022-03-23 16:08 [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem Lucas Stach
                   ` (2 preceding siblings ...)
  2022-03-23 16:08 ` [PATCH 4/4] drm/etnaviv: reap idle softpin mappings when necessary Lucas Stach
@ 2022-03-24 15:39 ` Philipp Zabel
  2022-03-31 10:50 ` Guido Günther
  4 siblings, 0 replies; 8+ messages in thread
From: Philipp Zabel @ 2022-03-24 15:39 UTC (permalink / raw)
  To: Lucas Stach, etnaviv; +Cc: Russell King, dri-devel, kernel, patchwork-lst

On Mi, 2022-03-23 at 17:08 +0100, Lucas Stach wrote:
> When the mapping is already reaped the unmap must be a no-op, as we
> would otherwise try to remove the mapping twice, corrupting the
> involved
> data structures.
> 
> Cc: stable@vger.kernel.org # 5.4
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>

Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>

regards
Philipp

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/4] drm/etnaviv: move MMU context ref/unref into map/unmap_gem
  2022-03-23 16:08 ` [PATCH 2/4] drm/etnaviv: move MMU context ref/unref into map/unmap_gem Lucas Stach
@ 2022-03-24 15:39   ` Philipp Zabel
  0 siblings, 0 replies; 8+ messages in thread
From: Philipp Zabel @ 2022-03-24 15:39 UTC (permalink / raw)
  To: Lucas Stach, etnaviv; +Cc: Russell King, dri-devel, kernel, patchwork-lst

On Mi, 2022-03-23 at 17:08 +0100, Lucas Stach wrote:
> This makes it a little more clear that the mapping holds a reference
> to the context once the buffer has been successfully mapped into that
> context and simplifies the error handling a bit.
> 
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>

Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>

regards
Philipp

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/4] drm/etnaviv: move flush_seq increment into etnaviv_iommu_map/unmap
  2022-03-23 16:08 ` [PATCH 3/4] drm/etnaviv: move flush_seq increment into etnaviv_iommu_map/unmap Lucas Stach
@ 2022-03-24 15:39   ` Philipp Zabel
  0 siblings, 0 replies; 8+ messages in thread
From: Philipp Zabel @ 2022-03-24 15:39 UTC (permalink / raw)
  To: Lucas Stach, etnaviv; +Cc: Russell King, dri-devel, kernel, patchwork-lst

On Mi, 2022-03-23 at 17:08 +0100, Lucas Stach wrote:
The flush sequence is a marker that the page tables have been changed
and any affected TLBs need to be flushed. Move the flush_seq increment
a little further down the call stack to place it next to the actual
page table manipulation. Not functional change.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>

Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>

regards
Philipp

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
  2022-03-23 16:08 [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem Lucas Stach
                   ` (3 preceding siblings ...)
  2022-03-24 15:39 ` [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem Philipp Zabel
@ 2022-03-31 10:50 ` Guido Günther
  4 siblings, 0 replies; 8+ messages in thread
From: Guido Günther @ 2022-03-31 10:50 UTC (permalink / raw)
  To: Lucas Stach; +Cc: etnaviv, dri-devel, patchwork-lst, kernel, Russell King

Hi Lucas,
On Wed, Mar 23, 2022 at 05:08:22PM +0100, Lucas Stach wrote:
> When the mapping is already reaped the unmap must be a no-op, as we
> would otherwise try to remove the mapping twice, corrupting the involved
> data structures.
> 
> Cc: stable@vger.kernel.org # 5.4
> Signed-off-by: Lucas Stach <l.stach@pengutronix.de>

Whole series

Tested-by: Guido Günther <agx@sigxcpu.org>
Acked-by: Guido Günther <agx@sigxcpu.org>

The code changes look good to me too but I got some details wrong too many times
for a `Reviewed-by:`

Cheers,
 -- Guido

> ---
>  drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
> index 9fb1a2aadbcb..aabb997a74eb 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
> @@ -286,6 +286,12 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
>  
>  	mutex_lock(&context->lock);
>  
> +	/* Bail if the mapping has been reaped by another thread */
> +	if (!mapping->context) {
> +		mutex_unlock(&context->lock);
> +		return;
> +	}
> +
>  	/* If the vram node is on the mm, unmap and remove the node */
>  	if (mapping->vram_node.mm == &context->mm)
>  		etnaviv_iommu_remove_mapping(context, mapping);
> -- 
> 2.30.2
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2022-03-31 10:51 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-23 16:08 [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem Lucas Stach
2022-03-23 16:08 ` [PATCH 2/4] drm/etnaviv: move MMU context ref/unref into map/unmap_gem Lucas Stach
2022-03-24 15:39   ` Philipp Zabel
2022-03-23 16:08 ` [PATCH 3/4] drm/etnaviv: move flush_seq increment into etnaviv_iommu_map/unmap Lucas Stach
2022-03-24 15:39   ` Philipp Zabel
2022-03-23 16:08 ` [PATCH 4/4] drm/etnaviv: reap idle softpin mappings when necessary Lucas Stach
2022-03-24 15:39 ` [PATCH 1/4] drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem Philipp Zabel
2022-03-31 10:50 ` Guido Günther

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.