drivers/gpu/drm/xe/xe_pagefault.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xe/xe_pagefault.c
Extension
.c
Size
12958 bytes
Lines
498
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

xe_vma_userptr_check_repin(to_userptr_vma(vma))) {
		struct xe_userptr_vma *uvma = to_userptr_vma(vma);

		err = xe_vma_userptr_pin_pages(uvma);
		if (err)
			return err;
	}

	/* Lock VM and BOs dma-resv */
	xe_validation_ctx_init(&ctx, &vm->xe->val, &exec, (struct xe_val_flags) {});
	drm_exec_until_all_locked(&exec) {
		err = xe_pagefault_begin(&exec, vma, tile->mem.vram,
					 needs_vram == 1);
		drm_exec_retry_on_contention(&exec);
		xe_validation_retry_on_oom(&ctx, &err);
		if (err)
			goto unlock_dma_resv;

		/* Bind VMA only to the GT that has faulted */
		trace_xe_vma_pf_bind(vma);
		xe_vm_set_validation_exec(vm, &exec);
		fence = xe_vma_rebind(vm, vma, BIT(tile->id));
		xe_vm_set_validation_exec(vm, NULL);
		if (IS_ERR(fence)) {
			err = PTR_ERR(fence);
			xe_validation_retry_on_oom(&ctx, &err);
			goto unlock_dma_resv;
		}
	}

	dma_fence_wait(fence, false);
	dma_fence_put(fence);

unlock_dma_resv:
	xe_validation_ctx_fini(&ctx);
	if (err == -EAGAIN)
		goto retry_userptr;

	return err;
}

static bool
xe_pagefault_access_is_atomic(enum xe_pagefault_access_type access_type)
{
	return (access_type & XE_PAGEFAULT_ACCESS_TYPE_MASK) == XE_PAGEFAULT_ACCESS_TYPE_ATOMIC;
}

static struct xe_vm *xe_pagefault_asid_to_vm(struct xe_device *xe, u32 asid)
{
	struct xe_vm *vm;

	down_read(&xe->usm.lock);
	vm = xa_load(&xe->usm.asid_to_vm, asid);
	if (vm && (xe_vm_in_fault_mode(vm) || xe_vm_has_scratch(vm)))
		xe_vm_get(vm);
	else
		vm = ERR_PTR(-EINVAL);
	up_read(&xe->usm.lock);

	return vm;
}

static int xe_pagefault_service(struct xe_pagefault *pf)
{
	struct xe_gt *gt = pf->gt;
	struct xe_device *xe = gt_to_xe(gt);
	struct xe_vm *vm;
	struct xe_vma *vma = NULL;
	int err;
	bool atomic;

	/* Producer flagged this fault to be nacked */
	if (pf->consumer.fault_type_level == XE_PAGEFAULT_TYPE_LEVEL_NACK)
		return -EFAULT;

	vm = xe_pagefault_asid_to_vm(xe, pf->consumer.asid);
	if (IS_ERR(vm))
		return PTR_ERR(vm);

	/*
	 * TODO: Change to read lock? Using write lock for simplicity.
	 */
	down_write(&vm->lock);

	if (xe_vm_is_closed(vm)) {
		err = -ENOENT;
		goto unlock_vm;
	}

	vma = xe_vm_find_vma_by_addr(vm, pf->consumer.page_addr);

Annotation

Implementation Notes