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
next prev 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