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 Original line Diff line number Diff line
@@ -4,7 +4,7 @@
 * Copyright (C) Linaro 2012
 * Copyright (C) Linaro 2012
 * Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
 * 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
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * 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)
static void ion_secure_cma_free(struct ion_buffer *buffer)
{
{
	int ret = 0;
	int ret = 0;
	u32 source_vm;
	int *source_vm_list;
	int source_nelems;
	int dest_vmid;
	int dest_vmid;
	int dest_perms;
	int dest_perms;
	struct ion_cma_buffer_info *info = buffer->priv_virt;
	struct ion_cma_buffer_info *info = buffer->priv_virt;


	source_vm = get_secure_vmid(buffer->flags);
	source_nelems = count_set_bits(buffer->flags & ION_FLAGS_CP_MASK);
	if (source_vm < 0) {
	source_vm_list = kcalloc(source_nelems, sizeof(*source_vm_list),
		pr_err("%s: Failed to get secure vmid\n", __func__);
				 GFP_KERNEL);
	if (!source_vm_list)
		return;
		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_vmid = VMID_HLOS;
	dest_perms = PERM_READ | PERM_WRITE | PERM_EXEC;
	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);
			       &dest_vmid, &dest_perms, 1);
	if (ret) {
	if (ret) {
		pr_err("%s: Not freeing memory since assign failed\n",
		pr_err("%s: Not freeing memory since assign failed\n",
		       __func__);
		       __func__);
		return;
		goto out_free_source;
	}
	}


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


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


	source_vm = VMID_HLOS;
	source_vm = VMID_HLOS;
	dest_vm = get_secure_vmid(flags);


	if (dest_vm < 0) {
	dest_nelems = count_set_bits(flags & ION_FLAGS_CP_MASK);
		pr_err("%s: Failed to get secure vmid\n", __func__);
	dest_vm_list = kcalloc(dest_nelems, sizeof(*dest_vm_list), GFP_KERNEL);
		return -EINVAL;
	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)
	for (count = 0; count < dest_nelems; count++) {
		dest_perms = PERM_READ;
		if (dest_vm_list[count] == VMID_CP_SEC_DISPLAY)
			dest_perms[count] = PERM_READ;
		else
		else
		dest_perms = PERM_READ | PERM_WRITE;
			dest_perms[count] = PERM_READ | PERM_WRITE;
	}


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


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

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


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


+3 −1
Original line number Original line Diff line number Diff line
@@ -2,7 +2,7 @@
 * drivers/staging/android/ion/ion_priv.h
 * drivers/staging/android/ion/ion_priv.h
 *
 *
 * Copyright (C) 2011 Google, Inc.
 * 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
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * 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 ion_heap_is_system_secure_heap_type(enum ion_heap_type type);
int get_secure_vmid(unsigned long flags);
int get_secure_vmid(unsigned long flags);
bool is_secure_vmid_valid(int vmid);
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
 * Functions to help assign/unassign sg_table for System Secure Heap
+24 −0
Original line number Original line Diff line number Diff line
@@ -31,6 +31,7 @@
#include <linux/highmem.h>
#include <linux/highmem.h>
#include <linux/cma.h>
#include <linux/cma.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/show_mem_notifier.h>
#include <linux/show_mem_notifier.h>
#include <asm/cacheflush.h>
#include <asm/cacheflush.h>
#include "../ion_priv.h"
#include "../ion_priv.h"
@@ -622,6 +623,29 @@ bool is_secure_vmid_valid(int vmid)
		vmid == VMID_CP_SPSS_SP);
		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)
int get_secure_vmid(unsigned long flags)
{
{
	if (flags & ION_FLAG_CP_TOUCH)
	if (flags & ION_FLAG_CP_TOUCH)
+3 −1
Original line number Original line 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
 * 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
 * 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,
	IPT_TYPE_MDP_WRITEBACK = 2,
};
};


#define ION_FLAGS_CP_MASK	0x7FFF0000

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