From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 59C2B606A33E for ; Wed, 11 Nov 2026 12:19:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=KiapajGH Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0FDFC10E325; Wed, 11 Nov 2026 12:18:55 +0000 (UTC) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) by gabe.freedesktop.org (Postfix) with ESMTPS id A8EE510E325 for ; Wed, 11 Nov 2026 12:18:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1794399530; x=1825935530; h=message-id:date:mime-version:subject:to:cc:references: from:in-reply-to:content-transfer-encoding; bh=mkFqJX62KijkMmgEeIt8jKa0wlwYNQ1L6nJBDkV8q4I=; b=KiapajGHE1EdnMRQ3a+jw4gOVjn0Qt1Ugwdt1X6HrT5z42p20cFvdmtM hFf+7bS/E1tXRsLckpqI4m9Iyxp3gNfLQG8LfojrAvpUaKhljlLGJTzOX 0exd+BsDeBUXFzM1L+ttkw2sjKv915plhheNBFD3I1SH1U0EaPI/GO6Jt +RQgvk3MEMdLmdX38sp7kqupom5EtREMf4dSRRJFeZ3gIgDxTg+6uTTzQ iUFa7B/sSI5VWFTlr48jD2uZQkqKboxPNbOpUnfjJUK0hZj81lAwfMm/+ NTbV9krOxY5mOs3WpuRAMeCqxXAm+bah3vP0LM3y4obi73jsbGsRLAAPt A==; X-CSE-ConnectionGUID: OfOUG+PIQ3CnQsRpGQba5A== X-CSE-MsgGUID: ZEpljM4LRECWfecs4iXIvA== X-IronPort-AV: E=McAfee;i="6800,10657,11962"; a="3089709" X-IronPort-AV: E=Sophos;i="6.27,207,1787036400"; d="scan'208";a="3089709" Received: from orviesa006.jf.intel.com ([10.64.159.146]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Nov 2026 04:18:50 -0800 X-CSE-ConnectionGUID: 5OuONr73TrqjbVDNvRrmCQ== X-CSE-MsgGUID: dOjm/moxTrWpXx6pVxP/8w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,207,1787036400"; d="scan'208";a="8444842" Received: from kniemiec-mobl1.ger.corp.intel.com (HELO [10.245.245.160]) ([10.245.245.160]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Nov 2026 04:18:48 -0800 Message-ID: Date: Wed, 11 Nov 2026 12:18:45 +0000 X-Archived-By: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] drm/xe/dma-buf: Validate BOs on export to charge the exporter To: =?UTF-8?Q?Thomas_Hellstr=C3=B6m?= , intel-xe@lists.freedesktop.org Cc: Matthew Brost , Dave Airlie , Rodrigo Vivi , stable@vger.kernel.org References: <20261111100929.2228-1-thomas.hellstrom@linux.intel.com> Content-Language: en-GB From: Matthew Auld In-Reply-To: <20261111100929.2228-1-thomas.hellstrom@linux.intel.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-BeenThere: intel-xe@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel Xe graphics driver List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Intel-xe" X-Spam-Status: No, score=-17.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE, SPF_PASS,USER_AGENT_SANE_1 autolearn=unavailable autolearn_force=no version=4.0.1 X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on aws-us-west-2-korg-listserv-alma10-1 On 11/11/2026 10:09, Thomas Hellström wrote: > xe_gem_prime_export() calls ttm_bo_setup_export() to make sure the > exporter is charged for the memory backing an exported BO. However, > that only populates a TTM_PL_SYSTEM tt. A BO that has been evicted, or > that has deferred backing, will instead get its memory allocated when > the importer maps it. For p2p imports this happens through > xe_bo_validate() in xe_dma_buf_map(), so the importer, not the > exporter, is charged for the allocation. > > Call xe_bo_validate() at export time instead, so that the BO is moved > into its preferred placement and the exporter is charged. Is it maybe also worth mentioning somewhere the unreclaimable pages angle? I could be mistaken here, but I think that was maybe also the issue I saw in a workload. For example: 1. Create say 100G VRAM buffer. Use DEFERRED. This leaves lingering tt structure. 2. Validate it on native side. This is now resident in VRAM. But still has lingering tt. 3. Export it. This now populates 100G worth of TT pages due to lingering tt. But we now have a populated VRAM buffer which is also populated with 100G TT pages. That 100G TT pages is not reclaimable and is hidden from shrinker since this still just looks like normal VRAM buffer. > > Do the purgeable checks and the validation in the same > xe_validation_guard() transaction, to avoid locking the BO twice. > > The commit message and code was drafted using LLM. > > Link: https://patchwork.freedesktop.org/patch/747480/?series=172524&rev=1 > Fixes: 91494dee1091 ("xe: populate buffers before exporting them.") > Cc: Matthew Brost > Cc: Matthew Auld > Cc: Dave Airlie > Cc: Rodrigo Vivi > Cc: intel-xe@lists.freedesktop.org > Cc: # v6.18+ > Signed-off-by: Thomas Hellström Reviewed-by: Matthew Auld > --- > drivers/gpu/drm/xe/xe_dma_buf.c | 76 +++++++++++++++++---------------- > 1 file changed, 39 insertions(+), 37 deletions(-) > > diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c > index 5bf13dc4b61d..90c9b90de552 100644 > --- a/drivers/gpu/drm/xe/xe_dma_buf.c > +++ b/drivers/gpu/drm/xe/xe_dma_buf.c > @@ -263,60 +263,62 @@ struct drm_gem_object *xe_dma_buf_to_gem(struct drm_device *dev, > struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags) > { > struct xe_bo *bo = gem_to_xe_bo(obj); > + struct xe_validation_ctx ctx; > + struct drm_exec exec; > struct dma_buf *buf; > - struct ttm_operation_ctx ctx = { > - .interruptible = true, > - .no_wait_gpu = true, > - /* We opt to avoid OOM on system pages allocations */ > - .gfp_retry_mayfail = true, > - .allow_res_evict = false, > - }; > - int ret; > + int ret = 0; > > if (bo->vm) > return ERR_PTR(-EPERM); > > - /* > - * Reject exporting purgeable BOs. DONTNEED BOs can be purged > - * at any time, making the exported dma-buf unusable. Purged BOs > - * have no backing store and are permanently invalid. > - */ > - ret = xe_bo_lock(bo, true); > - if (ret) > - return ERR_PTR(ret); > + xe_validation_guard(&ctx, &xe_bo_device(bo)->val, &exec, > + (struct xe_val_flags) {.interruptible = true}, ret) { > + ret = drm_exec_lock_obj(&exec, &bo->ttm.base); > + drm_exec_retry_on_contention(&exec); > + if (ret) > + break; > > - if (xe_bo_madv_is_dontneed(bo)) { > - ret = -EBUSY; > - goto out_unlock; > - } > + /* > + * Reject exporting purgeable BOs. DONTNEED BOs can be purged > + * at any time, making the exported dma-buf unusable. Purged BOs > + * have no backing store and are permanently invalid. > + */ > + if (xe_bo_madv_is_dontneed(bo)) { > + ret = -EBUSY; > + break; > + } > > - if (xe_bo_is_purged(bo)) { > - ret = -EINVAL; > - goto out_unlock; > - } > + if (xe_bo_is_purged(bo)) { > + ret = -EINVAL; > + break; > + } > > - xe_bo_willneed_get_locked(bo); > - xe_bo_unlock(bo); > + /* > + * Make sure the BO is backed in its preferred placement so that > + * the exporter, rather than the importer, is charged for the > + * memory allocation. > + */ > + ret = xe_bo_validate(bo, NULL, false, &exec); > + drm_exec_retry_on_contention(&exec); > + xe_validation_retry_on_oom(&ctx, &ret); > + if (ret) > + break; > > - ret = ttm_bo_setup_export(&bo->ttm, &ctx); > + xe_bo_willneed_get_locked(bo); > + } > if (ret) > - goto out_put; > + return ERR_PTR(ret); > > buf = drm_gem_prime_export(obj, flags); > if (IS_ERR(buf)) { > - ret = PTR_ERR(buf); > - goto out_put; > + xe_bo_lock(bo, false); > + xe_bo_willneed_put_locked(bo); > + xe_bo_unlock(bo); > + return buf; > } > > buf->ops = &xe_dmabuf_ops; > return buf; > - > -out_put: > - xe_bo_lock(bo, false); > - xe_bo_willneed_put_locked(bo); > -out_unlock: > - xe_bo_unlock(bo); > - return ERR_PTR(ret); > } > > static struct drm_gem_object *