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

Commit 33ae0436 authored by Sudarshan Rajagopalan's avatar Sudarshan Rajagopalan Committed by Gerrit - the friendly Code Review server
Browse files

msm: ion: Multiple vmids ION secure allocation



Support for ION allocations through secure cma
heap for multiple vmids.

Change-Id: I326e04155604c746f005b6b9bd53a5faf8a22cda
Signed-off-by: default avatarSudarshan Rajagopalan <sudaraja@codeaurora.org>
parent c934228c
Loading
Loading
Loading
Loading
+51 −19
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
 * Copyright (C) Linaro 2012
 * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
 *
 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
 * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
@@ -242,28 +242,37 @@ void ion_cma_heap_destroy(struct ion_heap *heap)
static void ion_secure_cma_free(struct ion_buffer *buffer)
{
	int ret = 0;
	u32 source_vm;
	int *source_vm_list;
	int source_nelems;
	int dest_vmid;
	int dest_perms;
	struct ion_cma_buffer_info *info = buffer->priv_virt;

	source_vm = get_secure_vmid(buffer->flags);
	if (source_vm < 0) {
		pr_err("%s: Failed to get secure vmid\n", __func__);
	source_nelems = count_set_bits(buffer->flags & ION_FLAGS_CP_MASK);
	source_vm_list = kcalloc(source_nelems, sizeof(*source_vm_list),
				 GFP_KERNEL);
	if (!source_vm_list)
		return;
	ret = populate_vm_list(buffer->flags, source_vm_list, source_nelems);
	if (ret) {
		pr_err("%s: Failed to get secure vmids\n", __func__);
		goto out_free_source;
	}

	dest_vmid = VMID_HLOS;
	dest_perms = PERM_READ | PERM_WRITE | PERM_EXEC;

	ret = hyp_assign_table(info->table, &source_vm, 1,
	ret = hyp_assign_table(info->table, source_vm_list, source_nelems,
			       &dest_vmid, &dest_perms, 1);
	if (ret) {
		pr_err("%s: Not freeing memory since assign failed\n",
		       __func__);
		return;
		goto out_free_source;
	}

	ion_cma_free(buffer);
out_free_source:
	kfree(source_vm_list);
}

static int ion_secure_cma_allocate(
@@ -272,41 +281,64 @@ static int ion_secure_cma_allocate(
			unsigned long align, unsigned long flags)
{
	int ret = 0;
	int count;
	int source_vm;
	int dest_vm;
	int dest_perms;
	int *dest_vm_list = NULL;
	int *dest_perms = NULL;
	int dest_nelems;
	struct ion_cma_buffer_info *info;

	source_vm = VMID_HLOS;
	dest_vm = get_secure_vmid(flags);

	if (dest_vm < 0) {
		pr_err("%s: Failed to get secure vmid\n", __func__);
		return -EINVAL;
	dest_nelems = count_set_bits(flags & ION_FLAGS_CP_MASK);
	dest_vm_list = kcalloc(dest_nelems, sizeof(*dest_vm_list), GFP_KERNEL);
	if (!dest_vm_list) {
		ret = -ENOMEM;
		goto out;
	}
	dest_perms = kcalloc(dest_nelems, sizeof(*dest_perms), GFP_KERNEL);
	if (!dest_perms) {
		ret = -ENOMEM;
		goto out_free_dest_vm;
	}
	ret = populate_vm_list(flags, dest_vm_list, dest_nelems);
	if (ret) {
		pr_err("%s: Failed to get secure vmid(s)\n", __func__);
		goto out_free_dest;
	}

	if (dest_vm == VMID_CP_SEC_DISPLAY)
		dest_perms = PERM_READ;
	for (count = 0; count < dest_nelems; count++) {
		if (dest_vm_list[count] == VMID_CP_SEC_DISPLAY)
			dest_perms[count] = PERM_READ;
		else
		dest_perms = PERM_READ | PERM_WRITE;
			dest_perms[count] = PERM_READ | PERM_WRITE;
	}

	ret = ion_cma_allocate(heap, buffer, len, align, flags);
	if (ret) {
		dev_err(heap->priv, "Unable to allocate cma buffer");
		return ret;
		goto out_free_dest;
	}

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

	kfree(dest_vm_list);
	kfree(dest_perms);
	return ret;

err:
	ion_secure_cma_free(buffer);
out_free_dest:
	kfree(dest_perms);
out_free_dest_vm:
	kfree(dest_vm_list);
out:
	return ret;
}

+3 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 * drivers/staging/android/ion/ion_priv.h
 *
 * Copyright (C) 2011 Google, Inc.
 * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
 * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
@@ -294,6 +294,8 @@ long msm_ion_custom_ioctl(struct ion_client *client,
int ion_heap_is_system_secure_heap_type(enum ion_heap_type type);
int get_secure_vmid(unsigned long flags);
bool is_secure_vmid_valid(int vmid);
unsigned int count_set_bits(unsigned long val);
int populate_vm_list(unsigned long flags, unsigned int *vm_list, int nelems);

/**
 * Functions to help assign/unassign sg_table for System Secure Heap
+24 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <linux/highmem.h>
#include <linux/cma.h>
#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/show_mem_notifier.h>
#include <asm/cacheflush.h>
#include "../ion_priv.h"
@@ -622,6 +623,29 @@ bool is_secure_vmid_valid(int vmid)
		vmid == VMID_CP_SPSS_SP);
}

unsigned int count_set_bits(unsigned long val)
{
	return ((unsigned int)bitmap_weight(&val, BITS_PER_LONG));
}

int populate_vm_list(unsigned long flags, unsigned int *vm_list,
		     int nelems)
{
	unsigned int itr = 0;
	int vmid;

	flags = flags & ION_FLAGS_CP_MASK;
	for_each_set_bit(itr, &flags, BITS_PER_LONG) {
		vmid = get_secure_vmid(0x1UL << itr);
		if (vmid < 0 || !nelems)
			return -EINVAL;

		vm_list[nelems - 1] = vmid;
		nelems--;
	}
	return 0;
}

int get_secure_vmid(unsigned long flags)
{
	if (flags & ION_FLAG_CP_TOUCH)
+3 −1
Original line number Diff line number Diff line
/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2016-2017, 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
@@ -22,6 +22,8 @@ enum ion_permission_type {
	IPT_TYPE_MDP_WRITEBACK = 2,
};

#define ION_FLAGS_CP_MASK	0x7FFF0000

/*
 * This flag allows clients when mapping into the IOMMU to specify to
 * defer un-mapping from the IOMMU until the buffer memory is freed.