kgsl_ioctl_gpumem_alloc

本文深入解析了GPU内存分配过程,包括ioctl命令、函数kgsl_ioctl_gpumem_alloc、数据结构kgsl_gpumem_alloc及其实现细节。同时,介绍了kgsl_mem_entry、kgsl_memdesc等关键数据结构的作用和创建流程。
static const struct kgsl_ioctl kgsl_ioctl_funcs[] = {
   
   
    ...
    // ioctl命令:IOCTL_KGSL_GPUMEM_ALLOC
    // ioctl函数:kgsl_ioctl_gpumem_alloc
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC,
			kgsl_ioctl_gpumem_alloc),
    ...
}

1. kgsl_gpumem_alloc

struct kgsl_gpumem_alloc {
   
   
    // 返回值:GPU内存地址
	unsigned long gpuaddr; /* output param */
    // 申请的内存大小
	__kernel_size_t size;
    // 标志位
	unsigned int flags;
};

// ioctl参数:kgsl_gpumem_alloc
#define IOCTL_KGSL_GPUMEM_ALLOC \
	_IOWR(KGSL_IOC_TYPE, 0x2f, struct kgsl_gpumem_alloc)

2. kgsl_ioctl_gpumem_alloc

long kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv,
		unsigned int cmd, void *data)
{
   
   
	struct kgsl_device *device = dev_priv->device;
    // ioctl命令参数
	struct kgsl_gpumem_alloc *param = data;
    
    // kgsl_mem_entry用于描述用户空间的内存分配[见2.1节]
	struct kgsl_mem_entry *entry;
	uint64_t flags = param->flags;

	/*
	 * On 64 bit kernel, secure memory region is expanded and
	 * moved to 64 bit address, 32 bit apps can not access it from
	 * this IOCTL.
	 */
	if ((param->flags & KGSL_MEMFLAGS_SECURE) && is_compat_task()
			&& test_bit(KGSL_MMU_64BIT, &device->mmu.features))
		return -EOPNOTSUPP;

	/* Legacy functions doesn't support these advanced features */
	flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP);

	if (is_compat_task())
		flags |= KGSL_MEMFLAGS_FORCE_32BIT;

    // 创建kgsl_mem_entry[见2.2节]
	entry = gpumem_alloc_entry(dev_priv, (uint64_t) param->size, flags);

	if (IS_ERR(entry))
		return PTR_ERR(entry);

    // 更新参数
	param->gpuaddr = (unsigned long) entry->memdesc.gpuaddr;
	param->size = (size_t) entry->memdesc.size;
	param->flags = (unsigned int) entry->memdesc.flags;

	/* Put the extra ref from kgsl_mem_entry_create() */
    // 减少引用计数, 如果引用计数减为0则通过kgsl_mem_entry_destroy释放kgsl_mem_entry
	kgsl_mem_entry_put(entry);

	return 0;
}

2.1 kgsl_mem_entry

/*
 * struct kgsl_mem_entry - a userspace memory allocation
 */
struct kgsl_mem_entry {
   
   
    // Currently userspace can only hold a single reference count but the kernel may hold more
	struct kref refcount;
    // description of the memory[见2.1.1节]
	struct kgsl_memdesc memdesc;
    // type-specific data, such as the dma-buf attachment pointer
	void *priv_data;
    // rb_node for the gpu address lookup rb tree
	struct rb_node node;
    // idr index for this entry, can be used to find memory that does not have a valid GPU address
	unsigned int id;
    // 持有该内存的进程
	struct kgsl_process_private *priv;
    // if !0, userspace requested that his memory be freed, but there are still references to it
	int pending_free;
    // String containing user specified metadata for the entry
	char metadata[KGSL_GPUOBJ_ALLOC_METADATA_MAX + 1];
    // used to schedule a kgsl_mem_entry_put in atomic contexts
	struct work_struct work;
	/**
	 * @map_count: Count how many vmas this object is mapped in - used for
	 * debugfs accounting
	 */
    // 映射的VMA数量
	atomic_t map_count;
};

2.1.1 kgsl_memdesc

/**
 * struct kgsl_memdesc - GPU memory object descriptor
 */
struct kgsl_memdesc {
   
   
    // Pointer to the pagetable that the object is mapped in
	struct kgsl_pagetable *pagetable;
    // Kernel virtual address
	void *hostptr;
    // Number of threads using hostptr
	unsigned int hostptr_count;
    // GPU virtual address
	uint64_t gpuaddr;
    // Physical address of the memory object
	phys_addr_t physaddr;
    // Size of the memory object
	uint64_t size;
    // Internal flags and settings
	unsigned int priv;
	struct sg_table *sgt;
    // Function hooks for the memdesc memory type[见2.1.2节]
	const struct kgsl_memdesc_ops *ops;
    // Flags set from userspace
	uint64_t flags;
	struct device *dev;
    // dma attributes for this memory
	unsigned long attrs;
    // An array of pointers to allocated pages
	struct page **pages;
    // Total number of pages allocated
	unsigned int page_count;
	/*
	 * @lock: Spinlock to protect the gpuaddr from being accessed by
	 * multiple entities trying to map the same SVM region at once
	 */
	spinlock_t lock;
	/** @shmem_filp: Pointer to the shmem file backing this memdesc */
    // 共享内存的文件
	struct file *shmem_filp;
	/** @ranges: rbtree base for the interval list of vbo ranges */
	struct rb_root_cached ranges;
	/** @ranges_lock: Mutex to protect the range database */
	struct mutex ranges_lock;
	/** @gmuaddr: GMU VA if this is mapped in GMU */
	u32 gmuaddr;
};

2.1.2 kgsl_memdesc_ops

struct kgsl_memdesc_ops {
   
   
	unsigned int vmflags;
	vm_fault_t (*vmfault)(struct kgsl_memdesc *memdesc,
		struct vm_area_struct *vma, struct vm_fault *vmf);
	void (*free)(struct kgsl_memdesc *memdesc);
	int (*map_kernel)(struct kgsl_memdesc *memdesc);
	void (*unmap_kernel)(struct kgsl_memdesc *memdesc);
	/**
	 * @put_gpuaddr: Put away the GPU address and unmap the memory
	 * descriptor
	 */
	void (*put_gpuaddr)(struct kgsl_memdesc *memdesc);
};

2.2 gpumem_alloc_entry

struct kgsl_mem_entry *gpumem_alloc_entry(
		struct kgsl_device_private *dev_priv,
		uint64_t size, uint64_t flags)
{
   
   
	int ret;
	struct kgsl_process_private *private = dev_priv->process_priv;
	struct kgsl_mem_entry *entry;
	struct kgsl_device *device = dev_priv->device;
	u32 cachemode;

	/* For 32-bit kernel world nothing to do with this flag */
	if (BITS_PER_LONG == 32)
		flags &= ~((uint64_t) KGSL_MEMFLAGS_FORCE_32BIT);

	if (flags & KGSL_MEMFLAGS_VBO)
		return gpumem_alloc_vbo_entry(dev_priv, size
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值