All of lore.kernel.org
 help / color / mirror / Atom feed
From: Adrian Larumbe <adrian.larumbe@collabora.com>
To: Boris Brezillon <boris.brezillon@collabora.com>
Cc: Steven Price <steven.price@arm.com>,
	Liviu Dudau <liviu.dudau@arm.com>,
	 Chris Diamand <chris.diamand@arm.com>,
	Akash Goel <akash.goel@arm.com>,
	 Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	Maxime Ripard <mripard@kernel.org>,
	 Thomas Zimmermann <tzimmermann@suse.de>,
	David Airlie <airlied@gmail.com>,
	 Simona Vetter <simona@ffwll.ch>,
	dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4 09/18] drm/panthor: Add fine-grained restrictions on VMs
Date: Fri, 11 Sep 2026 04:38:09 +0100	[thread overview]
Message-ID: <aqME16MO2AnA3KC0@sobremesa> (raw)
In-Reply-To: <20260826-panthor-unplug-fixes-v4-9-982cc8f4234b@collabora.com>

Reviewed-by: Adrián Larumbe <adrian.larumbe@collabora.com>

On 26.08.2026 16:56, Boris Brezillon wrote:
> We currently restrict what a VM is allowed to do based on two states:
> panthor_vm::destroyed and panthor_vm_pgtable::unusable, but we'll soon
> need a no-unmap restriction to fix the unplug logic.
> 
> Instead of adding a third boolean that would reflect this new limitation,
> let's overhaul the current restriction logic by adding separate
> restriction flags representing the operations we want to prevent (map,
> unmap and use).
> 
> Map and use restrictions are set everywhere we were previously
> calling panthor_vm_pgtable_declare_unusable() or setting ::destroyed
> to true, since that's what those two flags were preventing.
> 
> We also add restriction checks in
> panthor_vm_pgtable_prepare_[un]map_op_ctx() and
> panthor_vm_pgtable_exec_op() and drop the ones we had in
> panthor_vm_bind_job_create() since they are redundant.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
> ---
>  drivers/gpu/drm/panthor/panthor_mmu.c | 134 ++++++++++++++++++++++------------
>  1 file changed, 88 insertions(+), 46 deletions(-)
> 
> diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
> index 933cb820926d..3d9f9bf29e1d 100644
> --- a/drivers/gpu/drm/panthor/panthor_mmu.c
> +++ b/drivers/gpu/drm/panthor/panthor_mmu.c
> @@ -225,6 +225,25 @@ struct panthor_as_op_ctx {
>  	} map;
>  };
>  
> +/**
> + * enum panthor_as_restriction - List of restrictions that can apply to an AS.
> + *
> + * An AS always starts unrestricted, but based on the faults or device state
> + * changes, restrictions can be added over time. Restrictions can't be removed
> + * though. Once a VM is restricted, a new one must be created to lift the
> + * restrictions.
> + */
> +enum panthor_as_restriction {
> +	/** @PANTHOR_AS_FORBID_MAP: The AS can't map new buffers. */
> +	PANTHOR_AS_FORBID_MAP = BIT(0),
> +
> +	/** @PANTHOR_AS_FORBID_UNMAP: The AS can't remove existing mappings. */
> +	PANTHOR_AS_FORBID_UNMAP = BIT(1),
> +
> +	/** @PANTHOR_AS_FORBID_USE: The AS can't become active again. */
> +	PANTHOR_AS_FORBID_USE = BIT(2),
> +};
> +
>  /**
>   * struct panthor_as - Used to managed a GPU address space.
>   */
> @@ -285,25 +304,8 @@ struct panthor_as {
>  		struct list_head lru_node;
>  	} hw_slot;
>  
> -	/**
> -	 * @unusable: True if the AS has turned unusable because something
> -	 * bad happened during an asynchronous request.
> -	 *
> -	 * We don't try to recover from such failures, because this implies
> -	 * informing userspace about the specific operation that failed, and
> -	 * hoping the userspace driver can replay things from there. This all
> -	 * sounds very complicated for little gain.
> -	 *
> -	 * Instead, we should just flag the AS as unusable, and fail any
> -	 * further request targeting this AS.
> -	 *
> -	 * We also provide a way to query an AS state, so userspace can
> -	 * destroy it and create a new one.
> -	 *
> -	 * As an analogy, this would be mapped to a VK_ERROR_DEVICE_LOST
> -	 * situation, where the logical device needs to be re-created.
> -	 */
> -	bool unusable;
> +	/** @restrictions: Bitmask of panthor_as_restriction flags. */
> +	atomic_t restrictions;
>  
>  	/**
>  	 * @unhandled_fault: Unhandled fault happened.
> @@ -431,13 +433,6 @@ struct panthor_vm {
>  	/** @for_mcu: True if this is the MCU VM. */
>  	bool for_mcu;
>  
> -	/**
> -	 * @destroyed: True if the VM was destroyed.
> -	 *
> -	 * No further bind requests should be queued to a destroyed VM.
> -	 */
> -	bool destroyed;
> -
>  	/**
>  	 * @dummy: Dummy object used for sparse mappings.
>  	 *
> @@ -699,7 +694,9 @@ bool panthor_vm_has_unhandled_faults(struct panthor_vm *vm)
>   */
>  bool panthor_vm_is_unusable(struct panthor_vm *vm)
>  {
> -	return vm->as->unusable;
> +	return (atomic_read(&vm->as->restrictions) &
> +		(PANTHOR_AS_FORBID_USE | PANTHOR_AS_FORBID_MAP |
> +		 PANTHOR_AS_FORBID_UNMAP));
>  }
>  
>  static void panthor_as_release_hw_slot_locked(struct panthor_as *as)
> @@ -758,6 +755,11 @@ int panthor_vm_active(struct panthor_vm *vm)
>  	mutex_lock(&as->op_lock);
>  	mutex_lock(&ptdev->mmu->as.slots_lock);
>  
> +	if (atomic_read(&as->restrictions) & PANTHOR_AS_FORBID_USE) {
> +		ret = -EINVAL;
> +		goto out_unlock;
> +	}
> +
>  	if (refcount_inc_not_zero(&as->active_cnt))
>  		goto out_unlock;
>  
> @@ -926,21 +928,29 @@ static size_t get_pgsize(u64 addr, size_t size, size_t *count)
>  	return SZ_2M;
>  }
>  
> -static void panthor_as_declare_unusable(struct panthor_as *as)
> +static void panthor_as_restrict_usage_locked(struct panthor_as *as,
> +					     u32 new_restrictions)
>  {
>  	struct panthor_device *ptdev = container_of(as->base.drm, struct panthor_device, base);
>  	int cookie;
>  
> -	if (as->unusable)
> -		return;
> +	lockdep_assert_held(&as->op_lock);
>  
> -	as->unusable = true;
> -	mutex_lock(&ptdev->mmu->as.slots_lock);
> -	if (as->hw_slot.id >= 0 && drm_dev_enter(&ptdev->base, &cookie)) {
> -		panthor_mmu_as_disable(ptdev, as->hw_slot.id, false);
> -		drm_dev_exit(cookie);
> +	if (new_restrictions & PANTHOR_AS_FORBID_USE) {
> +		guard(mutex)(&ptdev->mmu->as.slots_lock);
> +		if (as->hw_slot.id >= 0 && drm_dev_enter(&ptdev->base, &cookie)) {
> +			/* Try to disable the AS. If as_disable() passed, this should cause
> +			 * a fault on the next memory access. If it failed, a reset is
> +			 * scheduled to recover from the GPU hang.
> +			 * We intentionally don't call release_as_locked() here, because
> +			 * this would mess up with the active_cnt refcount.
> +			 */
> +			panthor_mmu_as_disable(ptdev, as->hw_slot.id, false);
> +			drm_dev_exit(cookie);
> +		}
>  	}
> -	mutex_unlock(&ptdev->mmu->as.slots_lock);
> +
> +	atomic_or(new_restrictions, &as->restrictions);
>  }
>  
>  static void panthor_as_unmap_pages(struct panthor_as *as, u64 iova, u64 size)
> @@ -976,7 +986,9 @@ static void panthor_as_unmap_pages(struct panthor_as *as, u64 iova, u64 size)
>  			 * so flag the VM unusable to make sure it's not going
>  			 * to be used anymore.
>  			 */
> -			panthor_as_declare_unusable(as);
> +			panthor_as_restrict_usage_locked(as,
> +							 PANTHOR_AS_FORBID_USE |
> +							 PANTHOR_AS_FORBID_MAP);
>  
>  			/* If we don't make progress, we're screwed. That also means
>  			 * something else prevents us from unmapping the region, but
> @@ -1052,7 +1064,9 @@ panthor_as_map_pages(struct panthor_as *as, u64 iova, int prot,
>  				 * table pages behind.
>  				 */
>  				panthor_as_unmap_pages(as, start_iova, iova - start_iova);
> -				panthor_as_declare_unusable(as);
> +				panthor_as_restrict_usage_locked(as,
> +								 PANTHOR_AS_FORBID_USE |
> +								 PANTHOR_AS_FORBID_MAP);
>  				return ret;
>  			}
>  		}
> @@ -1349,6 +1363,9 @@ static int panthor_as_prepare_map_op_ctx(struct panthor_as_op_ctx *op_ctx,
>  	struct sg_table *sgt = NULL;
>  	int ret;
>  
> +	if (atomic_read(&as->restrictions) & PANTHOR_AS_FORBID_MAP)
> +		return -EINVAL;
> +
>  	if (!bo)
>  		return -EINVAL;
>  
> @@ -1442,6 +1459,9 @@ static int panthor_as_prepare_unmap_op_ctx(struct panthor_as_op_ctx *op_ctx,
>  	u32 pt_count = 0;
>  	int ret;
>  
> +	if (atomic_read(&as->restrictions) & PANTHOR_AS_FORBID_UNMAP)
> +		return -EINVAL;
> +
>  	memset(op_ctx, 0, sizeof(*op_ctx));
>  	op_ctx->va.range = size;
>  	op_ctx->va.addr = va;
> @@ -1652,7 +1672,12 @@ static void panthor_vm_destroy(struct panthor_vm *vm)
>  
>  	as = vm->as;
>  	ptdev = container_of(as->base.drm, struct panthor_device, base);
> -	vm->destroyed = true;
> +
> +	scoped_guard(mutex, &as->op_lock) {
> +		panthor_as_restrict_usage_locked(as,
> +						 PANTHOR_AS_FORBID_USE |
> +						 PANTHOR_AS_FORBID_MAP);
> +	}
>  
>  	/* Tell scheduler to stop all GPU work related to this VM */
>  	if (refcount_read(&as->active_cnt) > 0)
> @@ -2169,7 +2194,7 @@ struct panthor_heap_pool *panthor_vm_get_heap_pool(struct panthor_vm *vm, bool c
>  
>  	mutex_lock(&vm->heaps.lock);
>  	if (!vm->heaps.pool && create) {
> -		if (vm->destroyed)
> +		if (panthor_vm_is_unusable(vm))
>  			pool = ERR_PTR(-EINVAL);
>  		else
>  			pool = panthor_heap_pool_create(ptdev, vm);
> @@ -2546,6 +2571,17 @@ int panthor_vm_evict_bo_mappings_locked(struct panthor_gem_object *bo)
>  		if (!mutex_trylock(&as->op_lock))
>  			return -EDEADLK;
>  
> +		/* Unmaps are forbidden when we failed to communicate with the GPU,
> +		 * meaning we can't guarantee that the GPU will see our page table
> +		 * updates which might lead to UAF situations. In that case, we
> +		 * just skip eviction on this VM. Things should go back to normal
> +		 * after a GPU reset.
> +		 */
> +		if (atomic_read(&as->restrictions) & PANTHOR_AS_FORBID_UNMAP) {
> +			ret = -EBUSY;
> +			goto unlock_op;
> +		}
> +
>  		/* It can be that the vm_bo was already evicted but a new
>  		 * mapping pointing to this BO got created in the meantime,
>  		 * thus turning the vm_bo in partially evicted state. In that case
> @@ -2581,6 +2617,7 @@ int panthor_vm_evict_bo_mappings_locked(struct panthor_gem_object *bo)
>  			vma->evicted = true;
>  		}
>  
> +unlock_op:
>  		mutex_unlock(&as->op_lock);
>  
>  		if (ret)
> @@ -2795,7 +2832,7 @@ static int panthor_as_exec_op(struct panthor_as *as,
>  			.map.gem.offset = op->map.bo_offset,
>  		};
>  
> -		if (as->unusable) {
> +		if (atomic_read(&as->restrictions) & PANTHOR_AS_FORBID_MAP) {
>  			ret = -EINVAL;
>  			break;
>  		}
> @@ -2805,6 +2842,11 @@ static int panthor_as_exec_op(struct panthor_as *as,
>  	}
>  
>  	case DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP:
> +		if (atomic_read(&as->restrictions) & PANTHOR_AS_FORBID_UNMAP) {
> +			ret = -EINVAL;
> +			break;
> +		}
> +
>  		ret = drm_gpuvm_sm_unmap(&as->base, as, op->va.addr, op->va.range);
>  		break;
>  
> @@ -2816,8 +2858,11 @@ static int panthor_as_exec_op(struct panthor_as *as,
>  	panthor_as_unlock_region(as);
>  
>  out:
> -	if (ret && flag_vm_unusable_on_failure)
> -		panthor_as_declare_unusable(as);
> +	if (ret && flag_vm_unusable_on_failure) {
> +		panthor_as_restrict_usage_locked(as,
> +						 PANTHOR_AS_FORBID_USE |
> +						 PANTHOR_AS_FORBID_MAP);
> +	}
>  
>  	as->op_ctx = NULL;
>  	mutex_unlock(&as->op_lock);
> @@ -3141,9 +3186,6 @@ panthor_vm_bind_job_create(struct drm_file *file,
>  	if (!vm)
>  		return ERR_PTR(-EINVAL);
>  
> -	if (vm->destroyed || vm->as->unusable)
> -		return ERR_PTR(-EINVAL);
> -
>  	job = kzalloc_obj(*job);
>  	if (!job)
>  		return ERR_PTR(-ENOMEM);
> 
> -- 
> 2.55.0

Adrian Larumbe

  reply	other threads:[~2026-09-11  3:38 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-26 14:55 [PATCH v4 00/18] drm/panthor: Fix the unplug logic Boris Brezillon
2026-08-26 14:56 ` [PATCH v4 01/18] drm/panthor: Disable reset work before unplug Boris Brezillon
2026-08-27 13:00   ` Liviu Dudau
2026-09-10  1:12   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 02/18] drm/panthor: Revisit the reset logic to avoid reset request loss Boris Brezillon
2026-08-27 15:04   ` Liviu Dudau
2026-09-10  1:13   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 03/18] drm/panthor: Make panthor_device::pm::state non-atomic Boris Brezillon
2026-08-27 15:12   ` Liviu Dudau
2026-09-10  1:13   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 04/18] drm/panthor: Flush the cleanup_wq in the unplug path Boris Brezillon
2026-08-27 15:14   ` Liviu Dudau
2026-09-10  1:14   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 05/18] drm/panthor: Make the page table cache and cleanup workqueue device-local Boris Brezillon
2026-08-27 15:20   ` Liviu Dudau
2026-09-10  1:14   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 06/18] drm/panthor: Drop unused vm argument passed to panthor_vm_prepare_sync_only_op_ctx() Boris Brezillon
2026-08-27 15:21   ` Liviu Dudau
2026-09-10  1:15   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 07/18] drm/panthor: Move the debugfs initialization to panthor_device.c Boris Brezillon
2026-09-10  1:18   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 08/18] drm/panthor: Split panthor_vm Boris Brezillon
2026-09-11  3:37   ` Adrian Larumbe
2026-09-11  9:48     ` Boris Brezillon
2026-09-11 22:55   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 09/18] drm/panthor: Add fine-grained restrictions on VMs Boris Brezillon
2026-09-11  3:38   ` Adrian Larumbe [this message]
2026-08-26 14:56 ` [PATCH v4 10/18] drm/panthor: Check AS state before disabling Boris Brezillon
2026-09-11  3:38   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 11/18] drm/panthor: Don't pre-allocate VMAs or page tables when preparing a full VM unmap Boris Brezillon
2026-09-11  3:38   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 12/18] drm/panthor: Let l2_power_off return errors and force users to check it Boris Brezillon
2026-09-11  3:39   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 13/18] drm/panthor: Complain if the SOFT_RESET fails Boris Brezillon
2026-09-11  3:40   ` Adrian Larumbe
2026-09-11  9:54     ` Boris Brezillon
2026-08-26 14:56 ` [PATCH v4 14/18] drm/panthor: Make the VM cleanup path more robust against UAF Boris Brezillon
2026-09-11 19:15   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 15/18] drm/panthor: Track user owned VMs Boris Brezillon
2026-09-11 19:17   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 16/18] drm/panthor: Track user owned groups Boris Brezillon
2026-09-11 19:17   ` Adrian Larumbe
2026-08-26 14:56 ` [PATCH v4 17/18] drm/panthor: Fix the unplug logic Boris Brezillon
2026-09-11 22:44   ` Adrian Larumbe
2026-09-14  7:53     ` Boris Brezillon
2026-08-26 14:56 ` [PATCH v4 18/18] drm/panthor: Add debugfs knobs to simulate reset failures Boris Brezillon
2026-09-11 19:18   ` Adrian Larumbe
2026-09-12 19:27   ` Adrian Larumbe
2026-09-14  8:07     ` Boris Brezillon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aqME16MO2AnA3KC0@sobremesa \
    --to=adrian.larumbe@collabora.com \
    --cc=airlied@gmail.com \
    --cc=akash.goel@arm.com \
    --cc=boris.brezillon@collabora.com \
    --cc=chris.diamand@arm.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liviu.dudau@arm.com \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=simona@ffwll.ch \
    --cc=steven.price@arm.com \
    --cc=tzimmermann@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.