drivers/gpu/drm/xe/xe_vm.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xe/xe_vm.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_vm.c
Extension
.c
Size
125142 bytes
Lines
4964
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct xe_vma_lock_and_validate_flags {
	u32 res_evict : 1;
	u32 validate : 1;
	u32 request_decompress : 1;
	u32 check_purged : 1;
};

static int vma_lock_and_validate(struct drm_exec *exec, struct xe_vma *vma,
				 struct xe_vma_lock_and_validate_flags flags)
{
	struct xe_bo *bo = xe_vma_bo(vma);
	struct xe_vm *vm = xe_vma_vm(vma);
	bool validate_bo = flags.validate;
	int err = 0;

	if (bo) {
		if (!bo->vm)
			err = drm_exec_lock_obj(exec, &bo->ttm.base);

		/* Reject new mappings to DONTNEED/purged BOs; allow cleanup operations */
		if (!err && flags.check_purged) {
			if (xe_bo_madv_is_dontneed(bo))
				err = -EBUSY;  /* BO marked purgeable */
			else if (xe_bo_is_purged(bo))
				err = -EINVAL; /* BO already purged */
		}

		/* Don't validate the BO for DONTNEED/PURGED remap remnants. */
		if (vma->attr.purgeable_state != XE_MADV_PURGEABLE_WILLNEED)
			validate_bo = false;

		if (!err && validate_bo)
			err = xe_bo_validate(bo, vm,
					     xe_vm_allow_vm_eviction(vm) &&
					     flags.res_evict, exec);

		if (err)
			return err;

		if (flags.request_decompress)
			err = xe_bo_decompress(bo);
	}

	return err;
}

static int check_ufence(struct xe_vma *vma)
{
	if (vma->ufence) {
		struct xe_user_fence * const f = vma->ufence;

		if (!xe_sync_ufence_get_status(f))
			return -EBUSY;

		vma->ufence = NULL;
		xe_sync_ufence_put(f);
	}

	return 0;
}

static int prefetch_ranges(struct xe_vm *vm, struct xe_vma_op *op)
{
	bool devmem_possible = IS_DGFX(vm->xe) && IS_ENABLED(CONFIG_DRM_XE_PAGEMAP);
	struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va);
	struct drm_pagemap *dpagemap = op->prefetch_range.dpagemap;
	int err = 0;

	struct xe_svm_range *svm_range;
	struct drm_gpusvm_ctx ctx = {};
	unsigned long i;

	if (!xe_vma_is_cpu_addr_mirror(vma))
		return 0;

	ctx.read_only = xe_vma_read_only(vma);
	ctx.devmem_possible = devmem_possible;
	ctx.check_pages_threshold = devmem_possible ? SZ_64K : 0;
	ctx.device_private_page_owner = xe_svm_private_page_owner(vm, !dpagemap);

	/* TODO: Threading the migration */
	xa_for_each(&op->prefetch_range.range, i, svm_range) {
		if (!dpagemap)
			xe_svm_range_migrate_to_smem(vm, svm_range);

		if (IS_ENABLED(CONFIG_DRM_XE_DEBUG_VM)) {
			drm_dbg(&vm->xe->drm,
				"Prefetch pagemap is %s start 0x%016lx end 0x%016lx\n",
				dpagemap ? dpagemap->drm->unique : "system",
				xe_svm_range_start(svm_range), xe_svm_range_end(svm_range));

Annotation

Implementation Notes