Commit 0131514f authored by Thomas Hellström's avatar Thomas Hellström
Browse files

drm/xe: Pass down drm_exec context to validation



We want all validation (potential backing store allocation) to be part
of a drm_exec transaction. Therefore add a drm_exec pointer argument
to xe_bo_validate() and ___xe_bo_create_locked(). Upcoming patches
will deal with making all (or nearly all) calls to these functions
part of a drm_exec transaction. In the meantime, define special values
of the drm_exec pointer:

XE_VALIDATION_UNIMPLEMENTED: Implementation of the drm_exec transaction
has not been done yet.
XE_VALIDATION_UNSUPPORTED: Some Middle-layers (dma-buf) doesn't allow
the drm_exec context to be passed down to map_attachment where
validation takes place.
XE_VALIDATION_OPT_OUT: May be used only for kunit tests where exhaustive
eviction isn't crucial and the ROI of converting those is very
small.

For XE_VALIDATION_UNIMPLEMENTED and XE_VALIDATION_OPT_OUT there is also
a lockdep check that a drm_exec transaction can indeed start at the
location where the macro is expanded. This is to encourage
developers to take this into consideration early in the code
development process.

v2:
- Fix xe_vm_set_validation_exec() imbalance. Add an assert that
  hopefully catches future instances of this (Matt Brost)
v3:
- Extend to psmi_alloc_object

Signed-off-by: default avatarThomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com> #v3
Link: https://lore.kernel.org/r/20250908101246.65025-2-thomas.hellstrom@linux.intel.com
parent 0d40ea78
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ xe-y += xe_bb.o \
	xe_tuning.o \
	xe_uc.o \
	xe_uc_fw.o \
	xe_validation.o \
	xe_vm.o \
	xe_vm_madvise.o \
	xe_vram.o \
+4 −2
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

#include "xe_ttm_stolen_mgr.h"
#include "xe_res_cursor.h"
#include "xe_validation.h"

struct xe_bo;

@@ -20,6 +21,7 @@ static inline int i915_gem_stolen_insert_node_in_range(struct xe_device *xe,
						       u32 size, u32 align,
						       u32 start, u32 end)
{
	struct drm_exec *exec = XE_VALIDATION_UNIMPLEMENTED;
	struct xe_bo *bo;
	int err;
	u32 flags = XE_BO_FLAG_PINNED | XE_BO_FLAG_STOLEN;
@@ -34,13 +36,13 @@ static inline int i915_gem_stolen_insert_node_in_range(struct xe_device *xe,

	bo = xe_bo_create_locked_range(xe, xe_device_get_root_tile(xe),
				       NULL, size, start, end,
				       ttm_bo_type_kernel, flags, 0);
				       ttm_bo_type_kernel, flags, 0, exec);
	if (IS_ERR(bo)) {
		err = PTR_ERR(bo);
		bo = NULL;
		return err;
	}
	err = xe_bo_pin(bo);
	err = xe_bo_pin(bo, exec);
	xe_bo_unlock_vm_held(bo);

	if (err) {
+3 −2
Original line number Diff line number Diff line
@@ -281,6 +281,7 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb,
	struct i915_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL);
	struct drm_gem_object *obj = intel_fb_bo(&fb->base);
	struct xe_bo *bo = gem_to_xe_bo(obj);
	struct drm_exec *exec = XE_VALIDATION_UNIMPLEMENTED;
	int ret;

	if (!vma)
@@ -313,9 +314,9 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb,
		goto err;

	if (IS_DGFX(xe))
		ret = xe_bo_migrate(bo, XE_PL_VRAM0);
		ret = xe_bo_migrate(bo, XE_PL_VRAM0, exec);
	else
		ret = xe_bo_validate(bo, NULL, true);
		ret = xe_bo_validate(bo, NULL, true, exec);
	if (!ret)
		ttm_bo_pin(&bo->ttm);
	ttm_bo_unreserve(&bo->ttm);
+11 −9
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@

static int ccs_test_migrate(struct xe_tile *tile, struct xe_bo *bo,
			    bool clear, u64 get_val, u64 assign_val,
			    struct kunit *test)
			    struct kunit *test, struct drm_exec *exec)
{
	struct dma_fence *fence;
	struct ttm_tt *ttm;
@@ -35,7 +35,7 @@ static int ccs_test_migrate(struct xe_tile *tile, struct xe_bo *bo,
	u32 offset;

	/* Move bo to VRAM if not already there. */
	ret = xe_bo_validate(bo, NULL, false);
	ret = xe_bo_validate(bo, NULL, false, exec);
	if (ret) {
		KUNIT_FAIL(test, "Failed to validate bo.\n");
		return ret;
@@ -60,7 +60,7 @@ static int ccs_test_migrate(struct xe_tile *tile, struct xe_bo *bo,
	}

	/* Evict to system. CCS data should be copied. */
	ret = xe_bo_evict(bo);
	ret = xe_bo_evict(bo, exec);
	if (ret) {
		KUNIT_FAIL(test, "Failed to evict bo.\n");
		return ret;
@@ -132,6 +132,7 @@ static void ccs_test_run_tile(struct xe_device *xe, struct xe_tile *tile,

	/* TODO: Sanity check */
	unsigned int bo_flags = XE_BO_FLAG_VRAM_IF_DGFX(tile);
	struct drm_exec *exec = XE_VALIDATION_OPT_OUT;

	if (IS_DGFX(xe))
		kunit_info(test, "Testing vram id %u\n", tile->id);
@@ -149,18 +150,18 @@ static void ccs_test_run_tile(struct xe_device *xe, struct xe_tile *tile,

	kunit_info(test, "Verifying that CCS data is cleared on creation.\n");
	ret = ccs_test_migrate(tile, bo, false, 0ULL, 0xdeadbeefdeadbeefULL,
			       test);
			       test, exec);
	if (ret)
		goto out_unlock;

	kunit_info(test, "Verifying that CCS data survives migration.\n");
	ret = ccs_test_migrate(tile, bo, false, 0xdeadbeefdeadbeefULL,
			       0xdeadbeefdeadbeefULL, test);
			       0xdeadbeefdeadbeefULL, test, exec);
	if (ret)
		goto out_unlock;

	kunit_info(test, "Verifying that CCS data can be properly cleared.\n");
	ret = ccs_test_migrate(tile, bo, true, 0ULL, 0ULL, test);
	ret = ccs_test_migrate(tile, bo, true, 0ULL, 0ULL, test, exec);

out_unlock:
	xe_bo_unlock(bo);
@@ -210,6 +211,7 @@ static int evict_test_run_tile(struct xe_device *xe, struct xe_tile *tile, struc
	struct xe_bo *bo, *external;
	unsigned int bo_flags = XE_BO_FLAG_VRAM_IF_DGFX(tile);
	struct xe_vm *vm = xe_migrate_get_vm(xe_device_get_root_tile(xe)->migrate);
	struct drm_exec *exec = XE_VALIDATION_OPT_OUT;
	struct xe_gt *__gt;
	int err, i, id;

@@ -236,7 +238,7 @@ static int evict_test_run_tile(struct xe_device *xe, struct xe_tile *tile, struc
		}

		xe_bo_lock(external, false);
		err = xe_bo_pin_external(external, false);
		err = xe_bo_pin_external(external, false, exec);
		xe_bo_unlock(external);
		if (err) {
			KUNIT_FAIL(test, "external bo pin err=%pe\n",
@@ -294,7 +296,7 @@ static int evict_test_run_tile(struct xe_device *xe, struct xe_tile *tile, struc
		if (i) {
			down_read(&vm->lock);
			xe_vm_lock(vm, false);
			err = xe_bo_validate(bo, bo->vm, false);
			err = xe_bo_validate(bo, bo->vm, false, exec);
			xe_vm_unlock(vm);
			up_read(&vm->lock);
			if (err) {
@@ -303,7 +305,7 @@ static int evict_test_run_tile(struct xe_device *xe, struct xe_tile *tile, struc
				goto cleanup_all;
			}
			xe_bo_lock(external, false);
			err = xe_bo_validate(external, NULL, false);
			err = xe_bo_validate(external, NULL, false, exec);
			xe_bo_unlock(external);
			if (err) {
				KUNIT_FAIL(test, "external bo valid err=%pe\n",
+7 −5
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@ static bool is_dynamic(struct dma_buf_test_params *params)
}

static void check_residency(struct kunit *test, struct xe_bo *exported,
			    struct xe_bo *imported, struct dma_buf *dmabuf)
			    struct xe_bo *imported, struct dma_buf *dmabuf,
			    struct drm_exec *exec)
{
	struct dma_buf_test_params *params = to_dma_buf_test_params(test->priv);
	u32 mem_type;
@@ -62,7 +63,7 @@ static void check_residency(struct kunit *test, struct xe_bo *exported,
	 * importer is on a different device. If they're on the same device,
	 * the exporter and the importer should be the same bo.
	 */
	ret = xe_bo_evict(exported);
	ret = xe_bo_evict(exported, exec);
	if (ret) {
		if (ret != -EINTR && ret != -ERESTARTSYS)
			KUNIT_FAIL(test, "Evicting exporter failed with err=%d.\n",
@@ -77,7 +78,7 @@ static void check_residency(struct kunit *test, struct xe_bo *exported,
	}

	/* Re-validate the importer. This should move also exporter in. */
	ret = xe_bo_validate(imported, NULL, false);
	ret = xe_bo_validate(imported, NULL, false, exec);
	if (ret) {
		if (ret != -EINTR && ret != -ERESTARTSYS)
			KUNIT_FAIL(test, "Validating importer failed with err=%d.\n",
@@ -142,11 +143,12 @@ static void xe_test_dmabuf_import_same_driver(struct xe_device *xe)
			KUNIT_FAIL(test,
				   "xe_gem_prime_import() succeeded when it shouldn't have\n");
		} else {
			struct drm_exec *exec = XE_VALIDATION_OPT_OUT;
			int err;

			/* Is everything where we expect it to be? */
			xe_bo_lock(import_bo, false);
			err = xe_bo_validate(import_bo, NULL, false);
			err = xe_bo_validate(import_bo, NULL, false, exec);

			/* Pinning in VRAM is not allowed. */
			if (!is_dynamic(params) &&
@@ -159,7 +161,7 @@ static void xe_test_dmabuf_import_same_driver(struct xe_device *xe)
						  err == -ERESTARTSYS);

			if (!err)
				check_residency(test, bo, import_bo, dmabuf);
				check_residency(test, bo, import_bo, dmabuf, exec);
			xe_bo_unlock(import_bo);
		}
		drm_gem_object_put(import);
Loading