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

Commit 6716d27b authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ion: Add system secure heap" into msm-4.8

parents 9d1170a6 c1005d82
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
obj-$(CONFIG_ION) +=	ion.o ion_heap.o ion_page_pool.o ion_system_heap.o \
			ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o
			ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o \
			ion_system_secure_heap.o
obj-$(CONFIG_ION_TEST) += ion_test.o
ifdef CONFIG_COMPAT
obj-$(CONFIG_ION) += compat_ion.o
+6 −0
Original line number Diff line number Diff line
@@ -275,6 +275,7 @@ int ion_heap_buffer_zero(struct ion_buffer *buffer);
int ion_heap_pages_zero(struct page *page, size_t size, pgprot_t pgprot);

int msm_ion_heap_high_order_page_zero(struct page *page, int order);
struct ion_heap *get_ion_heap(int heap_id);
int msm_ion_heap_buffer_zero(struct ion_buffer *buffer);
int msm_ion_heap_pages_zero(struct page **pages, int num_pages);
int msm_ion_heap_alloc_pages_mem(struct pages_mem *pages_mem);
@@ -284,6 +285,8 @@ long msm_ion_custom_ioctl(struct ion_client *client,
			  unsigned int cmd,
			  unsigned long arg);

int ion_heap_is_system_secure_heap_type(enum ion_heap_type type);

/**
 * ion_heap_init_shrinker
 * @heap:		the heap
@@ -387,6 +390,9 @@ void ion_chunk_heap_destroy(struct ion_heap *);
struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *);
void ion_cma_heap_destroy(struct ion_heap *);

struct ion_heap *ion_system_secure_heap_create(struct ion_platform_heap *heap);
void ion_system_secure_heap_destroy(struct ion_heap *heap);

/**
 * kernel api to allocate/free from carveout -- used when carveout is
 * used to back an architecture specific custom heap
+216 −0
Original line number Diff line number Diff line
/*
 *
 * Copyright (c) 2014,2016 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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/slab.h>
#include <linux/msm_ion.h>
#include <soc/qcom/secure_buffer.h>
#include "ion.h"
#include "ion_priv.h"

struct ion_system_secure_heap {
	struct ion_heap *sys_heap;
	struct ion_heap heap;
};

static bool is_cp_flag_present(unsigned long flags)
{
	return flags && (ION_FLAG_CP_TOUCH ||
			ION_FLAG_CP_BITSTREAM ||
			ION_FLAG_CP_PIXEL ||
			ION_FLAG_CP_NON_PIXEL ||
			ION_FLAG_CP_CAMERA);
}

static int get_secure_vmid(unsigned long flags)
{
	if (flags & ION_FLAG_CP_TOUCH)
		return VMID_CP_TOUCH;
	if (flags & ION_FLAG_CP_BITSTREAM)
		return VMID_CP_BITSTREAM;
	if (flags & ION_FLAG_CP_PIXEL)
		return VMID_CP_PIXEL;
	if (flags & ION_FLAG_CP_NON_PIXEL)
		return VMID_CP_NON_PIXEL;
	if (flags & ION_FLAG_CP_CAMERA)
		return VMID_CP_CAMERA;

	return -EINVAL;
}

static void ion_system_secure_heap_free(struct ion_buffer *buffer)
{
	int ret = 0;
	u32 source_vm;
	int dest_vmid;
	int dest_perms;
	struct ion_heap *heap = buffer->heap;
	struct ion_system_secure_heap *secure_heap = container_of(heap,
						struct ion_system_secure_heap,
						heap);

	source_vm = get_secure_vmid(buffer->flags);
	if (source_vm < 0) {
		pr_info("%s: Unable to get secure VMID\n", __func__);
		return;
	}
	dest_vmid = VMID_HLOS;
	dest_perms = PERM_READ | PERM_WRITE;

	ret = hyp_assign_table(buffer->priv_virt, &source_vm, 1,
			       &dest_vmid, &dest_perms, 1);
	if (ret) {
		pr_err("%s: Not freeing memory since assign call failed\n",
		       __func__);
		return;
	}

	buffer->heap = secure_heap->sys_heap;
	secure_heap->sys_heap->ops->free(buffer);
}

static int ion_system_secure_heap_allocate(
					struct ion_heap *heap,
					struct ion_buffer *buffer,
					unsigned long size, unsigned long align,
					unsigned long flags)
{
	int ret = 0;
	u32 source_vm;
	int dest_vmid;
	int dest_perms;
	struct ion_system_secure_heap *secure_heap = container_of(heap,
						struct ion_system_secure_heap,
						heap);

	if (!ion_heap_is_system_secure_heap_type(secure_heap->heap.type) ||
	    !is_cp_flag_present(flags)) {
		pr_info("%s: Incorrect heap type or incorrect flags\n",
			__func__);
		return -EINVAL;
	}

	ret = secure_heap->sys_heap->ops->allocate(secure_heap->sys_heap,
						buffer, size, align, flags);
	if (ret) {
		pr_info("%s: Failed to get allocation for %s, ret = %d\n",
			__func__, heap->name, ret);
		return ret;
	}

	source_vm = VMID_HLOS;
	dest_vmid = get_secure_vmid(flags);
	if (dest_vmid < 0) {
		pr_info("%s: Unable to get secure VMID\n", __func__);
		ret = -EINVAL;
		goto err;
	}
	dest_perms = PERM_READ | PERM_WRITE;

	ret = hyp_assign_table(buffer->priv_virt, &source_vm, 1,
			       &dest_vmid, &dest_perms, 1);
	if (ret) {
		pr_err("%s: Assign call failed\n", __func__);
		goto err;
	}
	return ret;

err:
	ion_system_secure_heap_free(buffer);
	return ret;
}

static struct sg_table *ion_system_secure_heap_map_dma(
			struct ion_heap *heap, struct ion_buffer *buffer)
{
	struct ion_system_secure_heap *secure_heap = container_of(heap,
						struct ion_system_secure_heap,
						heap);

	return secure_heap->sys_heap->ops->map_dma(secure_heap->sys_heap,
							buffer);
}

static void ion_system_secure_heap_unmap_dma(struct ion_heap *heap,
					     struct ion_buffer *buffer)
{
	struct ion_system_secure_heap *secure_heap = container_of(heap,
						struct ion_system_secure_heap,
						heap);

	secure_heap->sys_heap->ops->unmap_dma(secure_heap->sys_heap,
							buffer);
}

static void *ion_system_secure_heap_map_kernel(struct ion_heap *heap,
					       struct ion_buffer *buffer)
{
	pr_info("%s: Kernel mapping from secure heap %s disallowed\n",
		__func__, heap->name);
	return ERR_PTR(-EINVAL);
}

static void ion_system_secure_heap_unmap_kernel(struct ion_heap *heap,
						struct ion_buffer *buffer)
{
}

static int ion_system_secure_heap_map_user(struct ion_heap *mapper,
					   struct ion_buffer *buffer,
					   struct vm_area_struct *vma)
{
	pr_info("%s: Mapping from secure heap %s disallowed\n",
		__func__, mapper->name);
	return -EINVAL;
}

static int ion_system_secure_heap_shrink(struct ion_heap *heap, gfp_t gfp_mask,
					 int nr_to_scan)
{
	struct ion_system_secure_heap *secure_heap = container_of(heap,
						struct ion_system_secure_heap,
						heap);

	return secure_heap->sys_heap->ops->shrink(secure_heap->sys_heap,
						gfp_mask, nr_to_scan);
}

static struct ion_heap_ops system_secure_heap_ops = {
	.allocate = ion_system_secure_heap_allocate,
	.free = ion_system_secure_heap_free,
	.map_dma = ion_system_secure_heap_map_dma,
	.unmap_dma = ion_system_secure_heap_unmap_dma,
	.map_kernel = ion_system_secure_heap_map_kernel,
	.unmap_kernel = ion_system_secure_heap_unmap_kernel,
	.map_user = ion_system_secure_heap_map_user,
	.shrink = ion_system_secure_heap_shrink,
};

struct ion_heap *ion_system_secure_heap_create(struct ion_platform_heap *unused)
{
	struct ion_system_secure_heap *heap;

	heap = kzalloc(sizeof(*heap), GFP_KERNEL);
	if (!heap)
		return ERR_PTR(-ENOMEM);
	heap->heap.ops = &system_secure_heap_ops;
	heap->heap.type = ION_HEAP_TYPE_SYSTEM_SECURE;
	heap->sys_heap = get_ion_heap(ION_SYSTEM_HEAP_ID);
	return &heap->heap;
}

void ion_system_secure_heap_destroy(struct ion_heap *heap)
{
	kfree(heap);
}
+31 −0
Original line number Diff line number Diff line
@@ -57,6 +57,10 @@ static struct ion_heap_desc ion_heap_meta[] = {
		.id	= ION_SYSTEM_CONTIG_HEAP_ID,
		.name	= ION_KMALLOC_HEAP_NAME,
	},
	{
		.id	= ION_SECURE_HEAP_ID,
		.name	= ION_SECURE_HEAP_NAME,
	},
	{
		.id	= ION_CP_MM_HEAP_ID,
		.name	= ION_MM_HEAP_NAME,
@@ -372,6 +376,7 @@ static struct heap_types_info {
	MAKE_HEAP_TYPE_MAPPING(CARVEOUT),
	MAKE_HEAP_TYPE_MAPPING(CHUNK),
	MAKE_HEAP_TYPE_MAPPING(DMA),
	MAKE_HEAP_TYPE_MAPPING(SYSTEM_SECURE),
};

static int msm_ion_get_heap_type_from_dt_node(struct device_node *node,
@@ -649,6 +654,11 @@ static int check_vaddr_bounds(unsigned long start, unsigned long end)
	return ret;
}

int ion_heap_is_system_secure_heap_type(enum ion_heap_type type)
{
	return type == ((enum ion_heap_type)ION_HEAP_TYPE_SYSTEM_SECURE);
}

int ion_heap_allow_heap_secure(enum ion_heap_type type)
{
	return false;
@@ -880,6 +890,9 @@ static struct ion_heap *msm_ion_heap_create(struct ion_platform_heap *heap_data)
	struct ion_heap *heap = NULL;

	switch ((int)heap_data->type) {
	case ION_HEAP_TYPE_SYSTEM_SECURE:
		heap = ion_system_secure_heap_create(heap_data);
		break;
	default:
		heap = ion_heap_create(heap_data);
	}
@@ -903,11 +916,29 @@ static void msm_ion_heap_destroy(struct ion_heap *heap)
		return;

	switch ((int)heap->type) {
	case ION_HEAP_TYPE_SYSTEM_SECURE:
		ion_system_secure_heap_destroy(heap);
		break;
	default:
		ion_heap_destroy(heap);
	}
}

struct ion_heap *get_ion_heap(int heap_id)
{
	int i;
	struct ion_heap *heap;

	for (i = 0; i < num_heaps; i++) {
		heap = heaps[i];
		if (heap->id == heap_id)
			return heap;
	}

	pr_err("%s: heap_id %d not found\n", __func__, heap_id);
	return NULL;
}

static int msm_ion_probe(struct platform_device *pdev)
{
	static struct ion_device *new_dev;
+15 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
enum msm_ion_heap_types {
	ION_HEAP_TYPE_MSM_START = ION_HEAP_TYPE_CUSTOM + 1,
	ION_HEAP_TYPE_SECURE_DMA = ION_HEAP_TYPE_MSM_START,
	ION_HEAP_TYPE_SYSTEM_SECURE,
	/*
	 * if you add a heap type here you should also add it to
	 * heap_types_info[] in msm_ion.c
@@ -24,6 +25,7 @@ enum msm_ion_heap_types {
enum ion_heap_ids {
	INVALID_HEAP_ID = -1,
	ION_CP_MM_HEAP_ID = 8,
	ION_SECURE_HEAP_ID = 9,
	ION_CP_MFC_HEAP_ID = 12,
	ION_CP_WB_HEAP_ID = 16, /* 8660 only */
	ION_CAMERA_HEAP_ID = 20, /* 8660 only */
@@ -65,6 +67,18 @@ enum cp_mem_usage {
	UNKNOWN = 0x7FFFFFFF,
};

/**
 * Flags to be used when allocating from the secure heap for
 * content protection
 */
#define ION_FLAG_CP_TOUCH ((1 << 17))
#define ION_FLAG_CP_BITSTREAM ((1 << 18))
#define ION_FLAG_CP_PIXEL  ((1 << 19))
#define ION_FLAG_CP_NON_PIXEL ((1 << 20))
#define ION_FLAG_CP_CAMERA ((1 << 21))
#define ION_FLAG_CP_HLOS ((1 << 22))
#define ION_FLAG_CP_HLOS_FREE ((1 << 23))

/**
 * Flag to use when allocating to indicate that a heap is secure.
 * Do NOT use BIT macro since it is defined in #ifdef __KERNEL__
@@ -110,6 +124,7 @@ enum cp_mem_usage {
#define ION_PIL1_HEAP_NAME  "pil_1"
#define ION_PIL2_HEAP_NAME  "pil_2"
#define ION_QSECOM_HEAP_NAME	"qsecom"
#define ION_SECURE_HEAP_NAME	"secure_heap"

#define ION_SET_CACHED(__cache)		((__cache) | ION_FLAG_CACHED)
#define ION_SET_UNCACHED(__cache)	((__cache) & ~ION_FLAG_CACHED)