Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Matthew Auld <matthew.auld@intel.com>
To: intel-xe@lists.freedesktop.org
Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Subject: [PATCH 2/3] drm/xe: Exclude imported dma-buf BOs from the TT budget
Date: Sat,  7 Nov 2026 17:26:51 +0000	[thread overview]
Message-ID: <20261107-oom-fun-v1-2-be9eb05b82ed@intel.com> (raw)
In-Reply-To: <20261107-oom-fun-v1-0-be9eb05b82ed@intel.com>

From: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>

The TT ("system") resource manager budget is sized to total host RAM
and enforced in xe_ttm_sys_mgr_new(). Imported dma-buf BOs
(ttm_bo_type_sg) placed in XE_PL_TT are backed by external pages and
never allocate from this device's TTM pool, so they consume no host
RAM. Charging them against the host-RAM-sized budget can falsely trip
it (e.g. many peer mappings on multi-GPU systems), surfacing as a
spurious -ENOSPC/OOM while memory is actually free.

Track the bytes of ttm_bo_type_sg BOs in a new per-device counter,
mem.sys_mgr_sg_usage, and subtract it from the usage compared against
the budget. The counter is maintained in xe_ttm_sys_mgr_new() and
xe_ttm_sys_mgr_del().

v2 (Matt, Sashiko)
  - Use a separate charged counter instead of subtracting import usage
    from the manager usage, avoiding an unsigned underflow race.
  - Don't dereference the BO in the free path, since the resource may
    have been transferred to a ghost object by then.
  - Make the memory region query report the charged usage.

Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
---
 drivers/gpu/drm/xe/xe_device_types.h |  6 ++++++
 drivers/gpu/drm/xe/xe_query.c        |  3 ++-
 drivers/gpu/drm/xe/xe_ttm_sys_mgr.c  | 38 ++++++++++++++++++++++++++++++++----
 drivers/gpu/drm/xe/xe_ttm_sys_mgr.h  |  3 +++
 4 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index d99881c6e1d5..c70f17ca8bba 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -298,6 +298,12 @@ struct xe_device {
 		struct xe_vram_region *vram;
 		/** @mem.sys_mgr: system TTM manager */
 		struct ttm_resource_manager sys_mgr;
+		/**
+		 * @mem.sys_mgr_charged: bytes charged against the @mem.sys_mgr
+		 * budget. Excludes imported dma-bufs (e.g. peer-GPU VRAM mapped
+		 * for P2P), which consume no local system memory.
+		 */
+		atomic64_t sys_mgr_charged;
 		/** @mem.shrinker: system memory shrinker. */
 		struct xe_shrinker *shrinker;
 		/** @mem.stolen_mgr: stolen memory manager. */
diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c
index dc975f595368..ab3a4ca79e75 100644
--- a/drivers/gpu/drm/xe/xe_query.c
+++ b/drivers/gpu/drm/xe/xe_query.c
@@ -27,6 +27,7 @@
 #include "xe_mmio.h"
 #include "xe_oa.h"
 #include "xe_pxp.h"
+#include "xe_ttm_sys_mgr.h"
 #include "xe_ttm_vram_mgr.h"
 #include "xe_vram_types.h"
 #include "xe_wa.h"
@@ -278,7 +279,7 @@ static int query_mem_regions(struct xe_device *xe,
 	mem_regions->mem_regions[0].instance = 0;
 	mem_regions->mem_regions[0].min_page_size = PAGE_SIZE;
 	mem_regions->mem_regions[0].total_size = man->size << PAGE_SHIFT;
-	mem_regions->mem_regions[0].used = ttm_resource_manager_usage(man);
+	mem_regions->mem_regions[0].used = xe_ttm_sys_mgr_usage(xe);
 	mem_regions->num_mem_regions = 1;
 
 	for (i = XE_PL_VRAM0; i <= XE_PL_VRAM1; ++i) {
diff --git a/drivers/gpu/drm/xe/xe_ttm_sys_mgr.c b/drivers/gpu/drm/xe/xe_ttm_sys_mgr.c
index 9d77ba605aec..24e2c690d992 100644
--- a/drivers/gpu/drm/xe/xe_ttm_sys_mgr.c
+++ b/drivers/gpu/drm/xe/xe_ttm_sys_mgr.c
@@ -16,9 +16,15 @@
 
 struct xe_ttm_sys_node {
 	struct ttm_buffer_object *tbo;
+	bool charged;
 	struct ttm_range_mgr_node base;
 };
 
+static atomic64_t *to_charged_usage(struct ttm_resource_manager *man)
+{
+	return &container_of(man, struct xe_device, mem.sys_mgr)->mem.sys_mgr_charged;
+}
+
 static inline struct xe_ttm_sys_node *
 to_xe_ttm_sys_node(struct ttm_resource *res)
 {
@@ -40,10 +46,21 @@ static int xe_ttm_sys_mgr_new(struct ttm_resource_manager *man,
 	node->tbo = tbo;
 	ttm_resource_init(tbo, place, &node->base.base);
 
-	if (!(place->flags & TTM_PL_FLAG_TEMPORARY) &&
-	    ttm_resource_manager_usage(man) > (man->size << PAGE_SHIFT)) {
-		r = -ENOSPC;
-		goto err_fini;
+	/*
+	 * Imported dma-bufs are backed by the exporter (possibly peer VRAM),
+	 * so don't charge them against the local system memory budget.
+	 */
+	if (tbo->type != ttm_bo_type_sg) {
+		u64 size = node->base.base.size;
+		u64 usage = atomic64_add_return(size, to_charged_usage(man));
+
+		if (!(place->flags & TTM_PL_FLAG_TEMPORARY) &&
+		    usage > (man->size << PAGE_SHIFT)) {
+			atomic64_sub(size, to_charged_usage(man));
+			r = -ENOSPC;
+			goto err_fini;
+		}
+		node->charged = true;
 	}
 
 	node->base.mm_nodes[0].start = 0;
@@ -65,6 +82,8 @@ static void xe_ttm_sys_mgr_del(struct ttm_resource_manager *man,
 {
 	struct xe_ttm_sys_node *node = to_xe_ttm_sys_node(res);
 
+	if (node->charged)
+		atomic64_sub(res->size, to_charged_usage(man));
 	ttm_resource_fini(man, res);
 	kfree(node);
 }
@@ -117,3 +136,14 @@ int xe_ttm_sys_mgr_init(struct xe_device *xe)
 	ttm_resource_manager_set_used(man, true);
 	return drmm_add_action_or_reset(&xe->drm, xe_ttm_sys_mgr_fini, xe);
 }
+
+/**
+ * xe_ttm_sys_mgr_usage() - System memory charged against the TT budget
+ * @xe: The xe device.
+ *
+ * Return: Bytes of system memory in use, excluding imported dma-bufs.
+ */
+u64 xe_ttm_sys_mgr_usage(struct xe_device *xe)
+{
+	return atomic64_read(&xe->mem.sys_mgr_charged);
+}
diff --git a/drivers/gpu/drm/xe/xe_ttm_sys_mgr.h b/drivers/gpu/drm/xe/xe_ttm_sys_mgr.h
index e8f5cd395b28..0b4678a05986 100644
--- a/drivers/gpu/drm/xe/xe_ttm_sys_mgr.h
+++ b/drivers/gpu/drm/xe/xe_ttm_sys_mgr.h
@@ -6,8 +6,11 @@
 #ifndef _XE_TTM_SYS_MGR_H_
 #define _XE_TTM_SYS_MGR_H_
 
+#include <linux/types.h>
+
 struct xe_device;
 
 int xe_ttm_sys_mgr_init(struct xe_device *xe);
+u64 xe_ttm_sys_mgr_usage(struct xe_device *xe);
 
 #endif

-- 
2.56.0

  parent reply	other threads:[~2026-11-07 17:27 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-07 17:26 [PATCH 0/3] Spurious OOM with P2P dma-buf imports on multi-GPU systems Matthew Auld
2026-11-07 17:26 ` [PATCH 1/3] drm/xe: don't allocate fake mmap offsets for imported dma-bufs Matthew Auld
2026-11-07 17:43   ` sashiko-bot
2026-11-07 17:26 ` Matthew Auld [this message]
2026-11-07 17:36   ` [PATCH 2/3] drm/xe: Exclude imported dma-buf BOs from the TT budget sashiko-bot
2026-11-07 17:26 ` [PATCH 3/3] drm/ttm, drm/xe: Drop the ttm_tt on null moves to VRAM Matthew Auld
2026-11-07 17:36 ` ✓ CI.KUnit: success for Spurious OOM with P2P dma-buf imports on multi-GPU systems Patchwork
2026-11-07 18:10 ` ✓ Xe.CI.BAT: " Patchwork
2026-11-08  8:22 ` ✓ Xe.CI.FULL: " Patchwork

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=20261107-oom-fun-v1-2-be9eb05b82ed@intel.com \
    --to=matthew.auld@intel.com \
    --cc=himal.prasad.ghimiray@intel.com \
    --cc=intel-xe@lists.freedesktop.org \
    /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