drivers/gpu/drm/xen/xen_drm_front_gem.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/xen/xen_drm_front_gem.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/xen/xen_drm_front_gem.c
Extension
.c
Size
7624 bytes
Lines
306
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 xen_gem_object {
	struct drm_gem_object base;

	size_t num_pages;
	struct page **pages;

	/* set for buffers allocated by the backend */
	bool be_alloc;

	/* this is for imported PRIME buffer */
	struct sg_table *sgt_imported;
};

static inline struct xen_gem_object *
to_xen_gem_obj(struct drm_gem_object *gem_obj)
{
	return container_of(gem_obj, struct xen_gem_object, base);
}

static int gem_alloc_pages_array(struct xen_gem_object *xen_obj,
				 size_t buf_size)
{
	xen_obj->num_pages = DIV_ROUND_UP(buf_size, PAGE_SIZE);
	xen_obj->pages = kvmalloc_objs(struct page *, xen_obj->num_pages);
	return !xen_obj->pages ? -ENOMEM : 0;
}

static void gem_free_pages_array(struct xen_gem_object *xen_obj)
{
	kvfree(xen_obj->pages);
	xen_obj->pages = NULL;
}

static int xen_drm_front_gem_object_mmap(struct drm_gem_object *gem_obj,
					 struct vm_area_struct *vma)
{
	struct xen_gem_object *xen_obj = to_xen_gem_obj(gem_obj);
	int ret;

	vma->vm_ops = gem_obj->funcs->vm_ops;

	/*
	 * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
	 * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
	 * the whole buffer.
	 */
	vm_flags_mod(vma, VM_MIXEDMAP | VM_DONTEXPAND, VM_PFNMAP);
	vma->vm_pgoff = 0;

	/*
	 * According to Xen on ARM ABI (xen/include/public/arch-arm.h):
	 * all memory which is shared with other entities in the system
	 * (including the hypervisor and other guests) must reside in memory
	 * which is mapped as Normal Inner Write-Back Outer Write-Back
	 * Inner-Shareable.
	 */
	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);

	/*
	 * vm_operations_struct.fault handler will be called if CPU access
	 * to VM is here. For GPUs this isn't the case, because CPU  doesn't
	 * touch the memory. Insert pages now, so both CPU and GPU are happy.
	 *
	 * FIXME: as we insert all the pages now then no .fault handler must
	 * be called, so don't provide one
	 */
	ret = vm_map_pages(vma, xen_obj->pages, xen_obj->num_pages);
	if (ret < 0)
		DRM_ERROR("Failed to map pages into vma: %d\n", ret);

	return ret;
}

static const struct vm_operations_struct xen_drm_drv_vm_ops = {
	.open           = drm_gem_vm_open,
	.close          = drm_gem_vm_close,
};

static const struct drm_gem_object_funcs xen_drm_front_gem_object_funcs = {
	.free = xen_drm_front_gem_object_free,
	.get_sg_table = xen_drm_front_gem_get_sg_table,
	.vmap = xen_drm_front_gem_prime_vmap,
	.vunmap = xen_drm_front_gem_prime_vunmap,
	.mmap = xen_drm_front_gem_object_mmap,
	.vm_ops = &xen_drm_drv_vm_ops,
};

static struct xen_gem_object *gem_create_obj(struct drm_device *dev,
					     size_t size)
{

Annotation

Implementation Notes