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

Commit e3fb5718 authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Check and set the private page flag for secure buffers



By convention we should set the private page flag on all secure
buffer chunks and we should check the flag when mapping to make
sure that we are only mapping secure buffers to secure pagetables
and vice versa.

Change-Id: Ic0dedbadb47c9c46dd1ee22e6a40421181c77692
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent c3aef20e
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -3027,6 +3027,18 @@ static int kgsl_setup_dma_buf(struct kgsl_mem_entry *entry,
	entry->memdesc.sglen = 0;

	for (s = entry->memdesc.sg; s != NULL; s = sg_next(s)) {
		int priv = (entry->memdesc.priv & KGSL_MEMDESC_SECURE) ? 1 : 0;

		/*
		 * Check that each chunk of of the sg table matches the secure
		 * flag.
		 */

		if (PagePrivate(sg_page(s)) != priv) {
			ret = -EPERM;
			goto out;
		}

		entry->memdesc.size += s->length;
		entry->memdesc.sglen++;
	}
+7 −3
Original line number Diff line number Diff line
@@ -924,7 +924,7 @@ int kgsl_cma_alloc_coherent(struct kgsl_device *device,
		goto err;
	}

	result = memdesc_sg_phys(memdesc, memdesc->physaddr, size);
	result = memdesc_sg_dma(memdesc, memdesc->physaddr, size);
	if (result)
		goto err;

@@ -1020,7 +1020,7 @@ int kgsl_cma_alloc_secure(struct kgsl_device *device,
		goto err;
	}

	result = memdesc_sg_phys(memdesc, memdesc->physaddr, size);
	result = memdesc_sg_dma(memdesc, memdesc->physaddr, size);
	if (result)
		goto err;

@@ -1029,6 +1029,9 @@ int kgsl_cma_alloc_secure(struct kgsl_device *device,
	if (result != 0)
		goto err;

	/* Set the private bit to indicate that we've secured this */
	SetPagePrivate(sg_page(memdesc->sg));

	memdesc->priv |= KGSL_MEMDESC_TZ_LOCKED;

	/* Record statistics */
@@ -1051,5 +1054,6 @@ static void kgsl_cma_unlock_secure(struct kgsl_memdesc *memdesc)
	if (memdesc->size == 0 || !(memdesc->priv & KGSL_MEMDESC_TZ_LOCKED))
		return;

	scm_lock_chunk(memdesc, 0);
	if (!scm_lock_chunk(memdesc, 0))
		ClearPagePrivate(sg_page(memdesc->sg));
}
+30 −0
Original line number Diff line number Diff line
@@ -155,6 +155,36 @@ memdesc_sg_phys(struct kgsl_memdesc *memdesc,
	return 0;
}

/**
 * memdesg_sg_dma() - Turn a dma_addr (from CMA) into a sg table
 * @memdesc: Pointer to the memdesc structure
 * @addr: Physical address from the dma_alloc function
 * @size: Size of the chunk
 *
 * Create a sg table for the contigious chunk specified by addr and size.
 */
static inline int
memdesc_sg_dma(struct kgsl_memdesc *memdesc,
		phys_addr_t addr, size_t size)
{
	struct page *page = phys_to_page(addr);

	memdesc->sg = kgsl_malloc(sizeof(struct scatterlist));
	if (memdesc->sg == NULL)
		return -ENOMEM;

	sg_set_page(memdesc->sg, page, size, 0);

	/*
	 * Continuing a grand tradition of doing it wrong this should be the
	 * dma_addr_t and not the phys_addr_t. But everything downstream of us
	 * assume this is a phys_addr_t so we do this.
	 */

	sg_dma_address(memdesc->sg) = addr;
	return 0;
}

/*
 * kgsl_memdesc_is_global - is this a globally mapped buffer?
 * @memdesc: the memdesc