Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fcb8f9f2 authored by Jordan Crouse's avatar Jordan Crouse Committed by Harshitha Sai Neelati
Browse files

msm: kgsl: Stop using memdesc->usermem



It shouldn't be illegal for memory descriptors to have multiple virtual
memory mappings under certain circumstances. If that is the case
tracking a single usermem address for each memdesc no longer makes much
sense. Get rid of the memdesc->usermem member and use an atomic counter
to track mappings instead.

Change-Id: Ic0dedbad31bafcd1019ccc8e68657cb7e3c72727
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent f291b2fb
Loading
Loading
Loading
Loading
+34 −19
Original line number Diff line number Diff line
@@ -254,6 +254,7 @@ static struct kgsl_mem_entry *kgsl_mem_entry_create(void)
		kref_get(&entry->refcount);
	}

	atomic_set(&entry->map_count, 0);
	return entry;
}

@@ -2332,7 +2333,7 @@ static int check_vma(unsigned long hostptr, u64 size)
	return true;
}

static int memdesc_sg_virt(struct kgsl_memdesc *memdesc)
static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, unsigned long useraddr)
{
	int ret = 0;
	long npages = 0, i;
@@ -2356,13 +2357,13 @@ static int memdesc_sg_virt(struct kgsl_memdesc *memdesc)
	}

	down_read(&current->mm->mmap_sem);
	if (!check_vma(memdesc->useraddr, memdesc->size)) {
	if (!check_vma(useraddr, memdesc->size)) {
		up_read(&current->mm->mmap_sem);
		ret = -EFAULT;
		goto out;
	}

	npages = get_user_pages(memdesc->useraddr, sglen, write, pages, NULL);
	npages = get_user_pages(useraddr, sglen, write, pages, NULL);
	up_read(&current->mm->mmap_sem);

	ret = (npages < 0) ? (int)npages : 0;
@@ -2400,7 +2401,6 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable,

	entry->memdesc.pagetable = pagetable;
	entry->memdesc.size = (uint64_t) size;
	entry->memdesc.useraddr = hostptr;
	entry->memdesc.flags |= (uint64_t)KGSL_MEMFLAGS_USERMEM_ADDR;

	if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
@@ -2408,15 +2408,15 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable,

		/* Register the address in the database */
		ret = kgsl_mmu_set_svm_region(pagetable,
			(uint64_t) entry->memdesc.useraddr, (uint64_t) size);
			(uint64_t) hostptr, (uint64_t) size);

		if (ret)
			return ret;

		entry->memdesc.gpuaddr = (uint64_t)  entry->memdesc.useraddr;
		entry->memdesc.gpuaddr = (uint64_t) hostptr;
	}

	return memdesc_sg_virt(&entry->memdesc);
	return memdesc_sg_virt(&entry->memdesc, hostptr);
}

#ifdef CONFIG_DMA_SHARED_BUFFER
@@ -2505,8 +2505,7 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device,
		return ret;
	}

	/* Setup the user addr/cache mode for cache operations */
	entry->memdesc.useraddr = hostptr;
	/* Setup the cache mode for cache operations */
	_setup_cache_mode(entry, vma);

	if (kgsl_mmu_has_feature(device, KGSL_MMU_IO_COHERENT) &&
@@ -3564,7 +3563,12 @@ long kgsl_ioctl_gpumem_get_info(struct kgsl_device_private *dev_priv,
	param->flags = (unsigned int) entry->memdesc.flags;
	param->size = (size_t) entry->memdesc.size;
	param->mmapsize = (size_t) kgsl_memdesc_footprint(&entry->memdesc);
	param->useraddr = entry->memdesc.useraddr;
	/*
	 * Entries can have multiple user mappings so thre isn't any one address
	 * we can report. Plus, the user should already know their mappings, so
	 * there isn't any value in reporting it back to them.
	 */
	param->useraddr = 0;

	kgsl_mem_entry_put(entry);
	return result;
@@ -3589,7 +3593,12 @@ long kgsl_ioctl_gpuobj_info(struct kgsl_device_private *dev_priv,
	param->flags = entry->memdesc.flags;
	param->size = entry->memdesc.size;
	param->va_len = kgsl_memdesc_footprint(&entry->memdesc);
	param->va_addr = (uint64_t) entry->memdesc.useraddr;
	/*
	 * Entries can have multiple user mappings so thre isn't any one address
	 * we can report. Plus, the user should already know their mappings, so
	 * there isn't any value in reporting it back to them.
	 */
	param->va_addr = 0;

	kgsl_mem_entry_put(entry);
	return 0;
@@ -3704,6 +3713,8 @@ static void kgsl_gpumem_vm_open(struct vm_area_struct *vma)

	if (kgsl_mem_entry_get(entry) == 0)
		vma->vm_private_data = NULL;

	atomic_inc(&entry->map_count);
}

static vm_fault_t
@@ -3727,9 +3738,13 @@ kgsl_gpumem_vm_close(struct vm_area_struct *vma)
	if (!entry)
		return;

	entry->memdesc.useraddr = 0;
	atomic64_sub(entry->memdesc.mapsize, &entry->priv->gpumem_mapped);
	entry->memdesc.mapsize = 0;
	/*
	 * Remove the memdesc from the mapped stat once all the mappings have
	 * gone away
	 */
	if (!atomic_dec_return(&entry->map_count))
		atomic64_sub(entry->memdesc.size, &entry->priv->gpumem_mapped);

	kgsl_mem_entry_put(entry);
}

@@ -3761,7 +3776,8 @@ get_mmap_entry(struct kgsl_process_private *private,
		goto err_put;
	}

	if (entry->memdesc.useraddr != 0) {
	/* Don't allow ourselves to remap user memory */
	if (entry->memdesc.flags & KGSL_MEMFLAGS_USERMEM_ADDR) {
		ret = -EBUSY;
		goto err_put;
	}
@@ -4018,12 +4034,11 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma)

	vma->vm_file = file;

	entry->memdesc.useraddr = vma->vm_start;
	atomic64_add(entry->memdesc.size, &entry->priv->gpumem_mapped);

	entry->memdesc.mapsize += entry->memdesc.size;
	atomic64_add(entry->memdesc.mapsize, &entry->priv->gpumem_mapped);
	atomic_inc(&entry->map_count);

	trace_kgsl_mem_mmap(entry);
	trace_kgsl_mem_mmap(entry, vma->vm_start);
	return 0;
}

+5 −4
Original line number Diff line number Diff line
@@ -184,11 +184,9 @@ struct kgsl_memdesc_ops {
 * @pagetable: Pointer to the pagetable that the object is mapped in
 * @hostptr: Kernel virtual address
 * @hostptr_count: Number of threads using hostptr
 * @useraddr: User virtual address (if applicable)
 * @gpuaddr: GPU virtual address
 * @physaddr: Physical address of the memory object
 * @size: Size of the memory object
 * @mapsize: Size of memory mapped in userspace
 * @priv: Internal flags and settings
 * @sgt: Scatter gather table for allocated pages
 * @ops: Function hooks for the memdesc memory type
@@ -202,11 +200,9 @@ struct kgsl_memdesc {
	struct kgsl_pagetable *pagetable;
	void *hostptr;
	unsigned int hostptr_count;
	unsigned long useraddr;
	uint64_t gpuaddr;
	phys_addr_t physaddr;
	uint64_t size;
	uint64_t mapsize;
	unsigned int priv;
	struct sg_table *sgt;
	const struct kgsl_memdesc_ops *ops;
@@ -271,6 +267,11 @@ struct kgsl_mem_entry {
	 * userspace
	 */
	u64 mapped;
	/**
	 * @map_count: Count how many vmas this object is mapped in - used for
	 * debugfs accounting
	 */
	atomic_t map_count;
};

struct kgsl_device_private;
+8 −4
Original line number Diff line number Diff line
@@ -184,7 +184,8 @@ static int print_mem_entry(void *data, void *ptr)
	flags[3] = get_alignflag(m);
	flags[4] = get_cacheflag(m);
	flags[5] = kgsl_memdesc_use_cpu_map(m) ? 'p' : '-';
	flags[6] = (m->useraddr) ? 'Y' : 'N';
	/* Show Y if at least one vma has this entry mapped (could be multiple) */
	flags[6] = atomic_read(&entry->map_count) ? 'Y' : 'N';
	flags[7] = kgsl_memdesc_is_secured(m) ?  's' : '-';
	flags[8] = '-';
	flags[9] = '\0';
@@ -197,10 +198,13 @@ static int print_mem_entry(void *data, void *ptr)

	seq_printf(s, "%pK %pK %16llu %5d %9s %10s %16s %5d %16llu %6d %6d",
			(uint64_t *)(uintptr_t) m->gpuaddr,
			(unsigned long *) m->useraddr,
			m->size, entry->id, flags,
			/*
			 * Show zero for the useraddr - we can't reliably track
			 * that value for multiple vmas anyway
			 */
			0, m->size, entry->id, flags,
			memtype_str(usermem_type),
			usage, (m->sgt ? m->sgt->nents : 0), m->mapsize,
			usage, (m->sgt ? m->sgt->nents : 0), m->size,
			egl_surface_count, egl_image_count);

	if (entry->metadata[0] != 0)
+3 −3
Original line number Diff line number Diff line
@@ -456,9 +456,9 @@ TRACE_EVENT(kgsl_mem_alloc,

TRACE_EVENT(kgsl_mem_mmap,

	TP_PROTO(struct kgsl_mem_entry *mem_entry),
	TP_PROTO(struct kgsl_mem_entry *mem_entry, unsigned long useraddr),

	TP_ARGS(mem_entry),
	TP_ARGS(mem_entry, useraddr),

	TP_STRUCT__entry(
		__field(unsigned long, useraddr)
@@ -470,7 +470,7 @@ TRACE_EVENT(kgsl_mem_mmap,
	),

	TP_fast_assign(
		__entry->useraddr = mem_entry->memdesc.useraddr;
		__entry->useraddr = useraddr;
		__entry->gpuaddr = mem_entry->memdesc.gpuaddr;
		__entry->size = mem_entry->memdesc.size;
		kgsl_get_memory_usage(__entry->usage, sizeof(__entry->usage),