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

Commit 286b115b authored by Jordan Crouse's avatar Jordan Crouse Committed by Pranav Patel
Browse files

msm: kgsl: Protect the memdesc->gpuaddr in SVM use cases



When SVM is being used there can only be one GPU address assigned
to the memory descriptor. Don't allow the GPU address to be changed
after it has been negotiated the first time by a process.

Change-Id: Ic0dedbad2a1b3ccdc2c1598a6c501b2be288d64e
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: default avatarHarshitha Sai Neelati <hsaine@codeaurora.org>
Signed-off-by: default avatarPranav Patel <pranavp@codeaurora.org>
parent 80db5e59
Loading
Loading
Loading
Loading
+26 −3
Original line number Diff line number Diff line
@@ -4283,19 +4283,34 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private,
{
	int ret;

	/*
	 * Protect access to the gpuaddr here to prevent multiple vmas from
	 * trying to map a SVM region at the same time
	 */
	spin_lock(&entry->memdesc.lock);

	if (entry->memdesc.gpuaddr) {
		spin_unlock(&entry->memdesc.lock);
		return (unsigned long) -EBUSY;
	}

	ret = kgsl_mmu_set_svm_region(private->pagetable, (uint64_t) addr,
		(uint64_t) size);

	if (ret != 0)
		return ret;
	if (ret != 0) {
		spin_unlock(&entry->memdesc.lock);
		return (unsigned long) ret;
	}

	entry->memdesc.gpuaddr = (uint64_t) addr;
	spin_unlock(&entry->memdesc.lock);

	entry->memdesc.pagetable = private->pagetable;

	ret = kgsl_mmu_map(private->pagetable, &entry->memdesc);
	if (ret) {
		kgsl_mmu_put_gpuaddr(&entry->memdesc);
		return ret;
		return (unsigned long) ret;
	}

	kgsl_memfree_purge(private->pagetable, entry->memdesc.gpuaddr,
@@ -4358,6 +4373,14 @@ static unsigned long _search_range(struct kgsl_process_private *private,
		result = _gpu_set_svm_region(private, entry, cpu, len);
		if (!IS_ERR_VALUE(result))
			break;
		/*
		 * _gpu_set_svm_region will return -EBUSY if we tried to set up
		 * SVM on an object that already has a GPU address. If
		 * that happens don't bother walking the rest of the
		 * region
		 */
		if ((long) result == -EBUSY)
			return -EBUSY;

		trace_kgsl_mem_unmapped_area_collision(entry, cpu, len);

+5 −0
Original line number Diff line number Diff line
@@ -225,6 +225,11 @@ struct kgsl_memdesc {
	struct page **pages;
	unsigned int page_count;
	unsigned int cur_bindings;
	/*
	 * @lock: Spinlock to protect the gpuaddr from being accessed by
	 * multiple entities trying to map the same SVM region at once
	 */
	spinlock_t lock;
};

/*
+6 −1
Original line number Diff line number Diff line
/* Copyright (c) 2011-2020, The Linux Foundation. All rights reserved.
/* Copyright (c) 2011-2021, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -2523,6 +2523,11 @@ static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable,
		goto out;
	}

	/*
	 * This path is only called in a non-SVM path with locks so we can be
	 * sure we aren't racing with anybody so we don't need to worry about
	 * taking the lock
	 */
	ret = _insert_gpuaddr(pagetable, addr, size);
	if (ret == 0) {
		memdesc->gpuaddr = addr;
+8 −2
Original line number Diff line number Diff line
/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2002,2007-2017,2021, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -450,10 +450,16 @@ void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc)
	if (PT_OP_VALID(pagetable, put_gpuaddr) && (unmap_fail == 0))
		pagetable->pt_ops->put_gpuaddr(memdesc);

	memdesc->pagetable = NULL;

	/*
	 * If SVM tries to take a GPU address it will lose the race until the
	 * gpuaddr returns to zero so we shouldn't need to worry about taking a
	 * lock here
	 */
	if (!kgsl_memdesc_is_global(memdesc))
		memdesc->gpuaddr = 0;

	memdesc->pagetable = NULL;
}
EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr);

+1 −0
Original line number Diff line number Diff line
@@ -797,6 +797,7 @@ void kgsl_memdesc_init(struct kgsl_device *device,
		(memdesc->flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT,
		ilog2(PAGE_SIZE));
	kgsl_memdesc_set_align(memdesc, align);
	spin_lock_init(&memdesc->lock);
}

int