public inbox for drm-ai-reviews@public-inbox.freedesktop.org
 help / color / mirror / Atom feed
From: Adrián Larumbe <adrian.larumbe@collabora.com>
To: linux-kernel@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org,
	Steven Price <steven.price@arm.com>,
	Boris Brezillon <boris.brezillon@collabora.com>,
	Janne Grunau <j@jannau.net>,
	kernel@collabora.com,
	Adrián Larumbe <adrian.larumbe@collabora.com>,
	Asahi Lina <lina+kernel@asahilina.net>,
	Caterina Shablia <caterina.shablia@collabora.com>,
	Danilo Krummrich <dakr@kernel.org>,
	Matthew Brost <matthew.brost@intel.com>,
	Thomas Hellström <thomas.hellstrom@linux.intel.com>,
	Alice Ryhl <aliceryhl@google.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>
Subject: [PATCH v5 06/11] drm/gpuvm: Add DRM_GPUVA_REPEAT flag and logic
Date: Fri, 13 Mar 2026 15:09:43 +0000	[thread overview]
Message-ID: <20260313150956.1618635-7-adrian.larumbe@collabora.com> (raw)
In-Reply-To: <20260313150956.1618635-1-adrian.larumbe@collabora.com>

From: Asahi Lina <lina+kernel@asahilina.net>

To be able to support "fake sparse" mappings without relying on GPU page
fault handling, drivers may need to create large (e.g. 4GiB) mappings of
the same page repeatedly (or same range of pages). Doing this through
individual mappings would be very wasteful. This can be handled better
by using a flag on map creation, but to do it safely, drm_gpuvm needs to
be aware of this special case.

Add a flag that signals that a given mapping is a page mapping, which is
repeated all over the entire requested VA range. This tweaks the
sm_map() logic to treat the GEM offsets differently when mappings are
a repeated ones so they are not incremented as they would be with regular
mappings.

The size of the GEM portion to repeat is passed through
drm_gpuva::gem::range. Most of the time it will be a page size, but
it can be bigger as long as it's less than drm_gpuva::va::range, and
drm_gpuva::va::range is a multiple of drm_gpuva::gem::range.

Signed-off-by: Asahi Lina <lina+kernel@asahilina.net>
Signed-off-by: Caterina Shablia <caterina.shablia@collabora.com>
---
 drivers/gpu/drm/drm_gpuvm.c | 67 ++++++++++++++++++++++++++++++++++---
 include/drm/drm_gpuvm.h     | 35 ++++++++++++++++++-
 2 files changed, 96 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c
index 0d9c821d1b34..ca7445f767fc 100644
--- a/drivers/gpu/drm/drm_gpuvm.c
+++ b/drivers/gpu/drm/drm_gpuvm.c
@@ -2340,6 +2340,8 @@ op_map_cb(const struct drm_gpuvm_ops *fn, void *priv,
 	op.map.va.range = req->map.va.range;
 	op.map.gem.obj = req->map.gem.obj;
 	op.map.gem.offset = req->map.gem.offset;
+	op.map.gem.repeat_range = req->map.gem.repeat_range;
+	op.map.flags = req->map.flags;
 
 	return fn->sm_step_map(&op, priv);
 }
@@ -2410,12 +2412,56 @@ static bool can_merge(struct drm_gpuvm *gpuvm, const struct drm_gpuva *va,
 	if (drm_WARN_ON(gpuvm->drm, b->va.addr > a->va.addr + a->va.range))
 		return false;
 
+	if (a->flags & DRM_GPUVA_REPEAT) {
+		u64 va_diff = b->va.addr - a->va.addr;
+
+		/* If this is a repeated mapping, both the GEM range
+		 * and offset must match.
+		 */
+		if (a->gem.repeat_range != b->gem.repeat_range ||
+		    a->gem.offset != b->gem.offset)
+			return false;
+
+		/* The difference between the VA addresses must be a
+		 * multiple of the repeated range, otherwise there's
+		 * a shift.
+		 */
+		if (do_div(va_diff, a->gem.repeat_range))
+			return false;
+
+		return true;
+	}
+
 	/* We intentionally ignore u64 underflows because all we care about
 	 * here is whether the VA diff matches the GEM offset diff.
 	 */
 	return b->va.addr - a->va.addr == b->gem.offset - a->gem.offset;
 }
 
+static int validate_map_request(struct drm_gpuvm *gpuvm,
+				const struct drm_gpuva_op_map *op)
+{
+	if (unlikely(!drm_gpuvm_range_valid(gpuvm, op->va.addr, op->va.range)))
+		return -EINVAL;
+
+	if (op->flags & DRM_GPUVA_REPEAT) {
+		u64 va_range = op->va.range;
+
+		/* For a repeated mapping, GEM range must be > 0
+		 * and a multiple of the VA range.
+		 */
+		if (unlikely(!op->gem.repeat_range ||
+			     va_range < op->gem.repeat_range ||
+			     do_div(va_range, op->gem.repeat_range)))
+			return -EINVAL;
+	}
+
+	if (op->flags & DRM_GPUVA_INVALIDATED)
+		return -EINVAL;
+
+	return 0;
+}
+
 static int
 __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 		   const struct drm_gpuvm_ops *ops, void *priv,
@@ -2429,7 +2475,8 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 	u64 req_end = req_addr + req_range;
 	int ret;
 
-	if (unlikely(!drm_gpuvm_range_valid(gpuvm, req_addr, req_range)))
+	ret = validate_map_request(gpuvm, &req->map);
+	if (unlikely(ret))
 		return -EINVAL;
 
 	drm_gpuvm_for_each_va_range_safe(va, next, gpuvm, req_addr, req_end) {
@@ -2463,7 +2510,9 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 					.va.addr = req_end,
 					.va.range = range - req_range,
 					.gem.obj = obj,
-					.gem.offset = offset + req_range,
+					.gem.repeat_range = va->gem.repeat_range,
+					.gem.offset = offset +
+						(va->flags & DRM_GPUVA_REPEAT ? 0 : req_range),
 					.flags = va->flags,
 				};
 				struct drm_gpuva_op_unmap u = {
@@ -2485,6 +2534,7 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 				.va.addr = addr,
 				.va.range = ls_range,
 				.gem.obj = obj,
+				.gem.repeat_range = va->gem.repeat_range,
 				.gem.offset = offset,
 				.flags = va->flags,
 			};
@@ -2526,7 +2576,9 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 					.va.addr = req_end,
 					.va.range = end - req_end,
 					.gem.obj = obj,
-					.gem.offset = offset + ls_range + req_range,
+					.gem.repeat_range = va->gem.repeat_range,
+					.gem.offset = offset + (va->flags & DRM_GPUVA_REPEAT ?
+								0 : ls_range + req_range),
 					.flags = va->flags,
 				};
 
@@ -2560,7 +2612,9 @@ __drm_gpuvm_sm_map(struct drm_gpuvm *gpuvm,
 					.va.addr = req_end,
 					.va.range = end - req_end,
 					.gem.obj = obj,
-					.gem.offset = offset + req_end - addr,
+					.gem.repeat_range = va->gem.repeat_range,
+					.gem.offset = offset +
+						(va->flags & DRM_GPUVA_REPEAT ? 0 : req_end - addr),
 					.flags = va->flags,
 				};
 				struct drm_gpuva_op_unmap u = {
@@ -2612,6 +2666,7 @@ __drm_gpuvm_sm_unmap(struct drm_gpuvm *gpuvm,
 			prev.va.addr = addr;
 			prev.va.range = req_addr - addr;
 			prev.gem.obj = obj;
+			prev.gem.repeat_range = va->gem.repeat_range;
 			prev.gem.offset = offset;
 			prev.flags = va->flags;
 
@@ -2622,7 +2677,9 @@ __drm_gpuvm_sm_unmap(struct drm_gpuvm *gpuvm,
 			next.va.addr = req_end;
 			next.va.range = end - req_end;
 			next.gem.obj = obj;
-			next.gem.offset = offset + (req_end - addr);
+			next.gem.repeat_range = va->gem.repeat_range;
+			next.gem.offset = offset +
+				(va->flags & DRM_GPUVA_REPEAT ? 0 : req_end - addr);
 			next.flags = va->flags;
 
 			next_split = true;
diff --git a/include/drm/drm_gpuvm.h b/include/drm/drm_gpuvm.h
index 5bf37deb282d..cd2f55bc1707 100644
--- a/include/drm/drm_gpuvm.h
+++ b/include/drm/drm_gpuvm.h
@@ -57,10 +57,19 @@ enum drm_gpuva_flags {
 	 */
 	DRM_GPUVA_SPARSE = (1 << 1),
 
+	/**
+	 * @DRM_GPUVA_REPEAT:
+	 *
+	 * Flag indicating that the &drm_gpuva is a mapping of a GEM
+	 * object with a certain range that is repeated multiple times to
+	 * fill the virtual address range.
+	 */
+	DRM_GPUVA_REPEAT = (1 << 2),
+
 	/**
 	 * @DRM_GPUVA_USERBITS: user defined bits
 	 */
-	DRM_GPUVA_USERBITS = (1 << 2),
+	DRM_GPUVA_USERBITS = (1 << 3),
 };
 
 #define VA_MERGE_MUST_MATCH_FLAGS (DRM_GPUVA_SPARSE)
@@ -114,6 +123,18 @@ struct drm_gpuva {
 		 */
 		u64 offset;
 
+		/**
+		 * @gem.repeat_range: the range of the GEM that is mapped
+		 *
+		 * When dealing with normal mappings, this must be zero.
+		 * When flags has DRM_GPUVA_REPEAT set, this field must be
+		 * smaller than va.range and va.range must be a multiple of
+		 * gem.repeat_range.
+		 * This is a u32 not a u64 because we expect repeated mappings
+		 * to be pointing to relatively small portions of a GEM object.
+		 */
+		u32 repeat_range;
+
 		/**
 		 * @gem.obj: the mapped &drm_gem_object
 		 */
@@ -883,6 +904,17 @@ struct drm_gpuva_op_map {
 		 */
 		u64 offset;
 
+		/**
+		 * @gem.repeat_range: the range of the GEM that is mapped
+		 *
+		 * When dealing with normal mappings, this must be zero.
+		 * When flags has DRM_GPUVA_REPEAT set, va.range must be
+		 * a multiple of gem.repeat_range. This is a u32 not a u64
+		 * because we expect repeated mappings to be pointing to
+		 * a relatively small portion of a GEM object.
+		 */
+		u32 repeat_range;
+
 		/**
 		 * @gem.obj: the &drm_gem_object to map
 		 */
@@ -1136,6 +1168,7 @@ static inline void drm_gpuva_init_from_op(struct drm_gpuva *va,
 	va->va.range = op->va.range;
 	va->gem.obj = op->gem.obj;
 	va->gem.offset = op->gem.offset;
+	va->gem.repeat_range = op->gem.repeat_range;
 }
 
 /**
-- 
2.53.0


  parent reply	other threads:[~2026-03-13 15:11 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-13 15:09 [PATCH v5 00/11] Support repeated mappings in GPUVM and Panthor Adrián Larumbe
2026-03-13 15:09 ` [PATCH v5 01/11] drm/panthor: Expose GPU page sizes to UM Adrián Larumbe
2026-03-13 20:48   ` Claude review: " Claude Code Review Bot
2026-03-13 15:09 ` [PATCH v5 02/11] drm/gpuvm: Remove dead code Adrián Larumbe
2026-03-13 20:48   ` Claude review: " Claude Code Review Bot
2026-03-13 15:09 ` [PATCH v5 03/11] drm/gpuvm: Fix comment to reflect remap operation operand status Adrián Larumbe
2026-03-13 20:48   ` Claude review: " Claude Code Review Bot
2026-03-13 15:09 ` [PATCH v5 04/11] drm/gpuvm: Add a helper to check if two VA can be merged Adrián Larumbe
2026-03-13 20:48   ` Claude review: " Claude Code Review Bot
2026-03-13 15:09 ` [PATCH v5 05/11] drm/gpuvm: Add a flags field to drm_gpuva_op_map Adrián Larumbe
2026-03-13 20:48   ` Claude review: " Claude Code Review Bot
2026-03-13 15:09 ` Adrián Larumbe [this message]
2026-03-13 20:48   ` Claude review: drm/gpuvm: Add DRM_GPUVA_REPEAT flag and logic Claude Code Review Bot
2026-03-13 15:09 ` [PATCH v5 07/11] drm/gpuvm: Ensure correctness of unmap/remaps of repeated regions Adrián Larumbe
2026-03-13 20:48   ` Claude review: " Claude Code Review Bot
2026-03-13 15:09 ` [PATCH v5 08/11] drm/panthor: Add support for repeated mappings Adrián Larumbe
2026-03-13 20:48   ` Claude review: " Claude Code Review Bot
2026-03-13 15:09 ` [PATCH v5 09/11] drm/panthor: Handle remap case " Adrián Larumbe
2026-03-13 20:48   ` Claude review: " Claude Code Review Bot
2026-03-13 15:09 ` [PATCH v5 10/11] drm/panthor: Pass vm_bind_op to vm_prepare_map_op_ctx Adrián Larumbe
2026-03-13 20:48   ` Claude review: " Claude Code Review Bot
2026-03-13 15:09 ` [PATCH v5 11/11] drm/panthor: Bump the driver version to 1.8 Adrián Larumbe
2026-03-13 20:48   ` Claude review: " Claude Code Review Bot
2026-03-13 20:48 ` Claude review: Support repeated mappings in GPUVM and Panthor Claude Code Review Bot

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=20260313150956.1618635-7-adrian.larumbe@collabora.com \
    --to=adrian.larumbe@collabora.com \
    --cc=airlied@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=boris.brezillon@collabora.com \
    --cc=caterina.shablia@collabora.com \
    --cc=dakr@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=j@jannau.net \
    --cc=kernel@collabora.com \
    --cc=lina+kernel@asahilina.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=matthew.brost@intel.com \
    --cc=mripard@kernel.org \
    --cc=simona@ffwll.ch \
    --cc=steven.price@arm.com \
    --cc=thomas.hellstrom@linux.intel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox