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

Commit f95f6b27 authored by Dinesh K Garg's avatar Dinesh K Garg Committed by Zhen Kong
Browse files

msm: mink: Add shared memory bridge support for smcinvoke driver



As per SHMBridge APIs, any memory that has to be shared with TZ
should come from SHMBridge. Usage of Linux kernel memory APIs
such as kmalloc() API is discouraged if memory has to be shared
with TZ. Hence, replacing kmalloc() API with corresponding
SHMBridge API.

Change-Id: Ib28392246d3e6ac6357e4a79bd59d7413f950eb7
Signed-off-by: default avatarZhen Kong <zkong@codeaurora.org>
Signed-off-by: default avatarDinesh K Garg <dineshg@codeaurora.org>
parent 1232e813
Loading
Loading
Loading
Loading
+33 −23
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@
#include <soc/qcom/scm.h>
#include <soc/qcom/scm.h>
#include <asm/cacheflush.h>
#include <asm/cacheflush.h>
#include <soc/qcom/qseecomi.h>
#include <soc/qcom/qseecomi.h>
#include <soc/qcom/qtee_shmbridge.h>


#include "smcinvoke_object.h"
#include "smcinvoke_object.h"
#include "../../misc/qseecom_kernel.h"
#include "../../misc/qseecom_kernel.h"
@@ -970,8 +971,10 @@ static bool is_inbound_req(int val)
		val == QSEOS_RESULT_BLOCKED_ON_LISTENER);
		val == QSEOS_RESULT_BLOCKED_ON_LISTENER);
}
}


static int prepare_send_scm_msg(const uint8_t *in_buf, size_t in_buf_len,
static int prepare_send_scm_msg(const uint8_t *in_buf, phys_addr_t in_paddr,
				uint8_t *out_buf, size_t out_buf_len,
				size_t in_buf_len,
				uint8_t *out_buf, phys_addr_t out_paddr,
				size_t out_buf_len,
				struct smcinvoke_cmd_req *req,
				struct smcinvoke_cmd_req *req,
				union smcinvoke_arg *args_buf,
				union smcinvoke_arg *args_buf,
				bool *tz_acked)
				bool *tz_acked)
@@ -986,9 +989,9 @@ static int prepare_send_scm_msg(const uint8_t *in_buf, size_t in_buf_len,
		return -EINVAL;
		return -EINVAL;


	desc.arginfo = SMCINVOKE_INVOKE_PARAM_ID;
	desc.arginfo = SMCINVOKE_INVOKE_PARAM_ID;
	desc.args[0] = (uint64_t)virt_to_phys(in_buf);
	desc.args[0] = (uint64_t)in_paddr;
	desc.args[1] = in_buf_len;
	desc.args[1] = in_buf_len;
	desc.args[2] = (uint64_t)virt_to_phys(out_buf);
	desc.args[2] = (uint64_t)out_paddr;
	desc.args[3] = out_buf_len;
	desc.args[3] = out_buf_len;
	cmd = SMCINVOKE_INVOKE_CMD;
	cmd = SMCINVOKE_INVOKE_CMD;
	dmac_flush_range(in_buf, in_buf + in_buf_len);
	dmac_flush_range(in_buf, in_buf + in_buf_len);
@@ -1507,6 +1510,7 @@ static long process_invoke_req(struct file *filp, unsigned int cmd,
	size_t inmsg_size = 0, outmsg_size = SMCINVOKE_TZ_MIN_BUF_SIZE;
	size_t inmsg_size = 0, outmsg_size = SMCINVOKE_TZ_MIN_BUF_SIZE;
	union  smcinvoke_arg *args_buf = NULL;
	union  smcinvoke_arg *args_buf = NULL;
	struct smcinvoke_file_data *tzobj = filp->private_data;
	struct smcinvoke_file_data *tzobj = filp->private_data;
	static struct qtee_shm in_shm = {0}, out_shm = {0};
	/*
	/*
	 * Hold reference to remote object until invoke op is not
	 * Hold reference to remote object until invoke op is not
	 * completed. Release once invoke is done.
	 * completed. Release once invoke is done.
@@ -1558,31 +1562,30 @@ static long process_invoke_req(struct file *filp, unsigned int cmd,
	}
	}


	inmsg_size = compute_in_msg_size(&req, args_buf);
	inmsg_size = compute_in_msg_size(&req, args_buf);
	in_msg = (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP,
	ret = qtee_shmbridge_allocate_shm(inmsg_size, &in_shm);
						get_order(inmsg_size));
	if (ret) {
	if (!in_msg) {
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto out;
		goto out;
	}
	}
	memset(in_msg, 0, inmsg_size);
	in_msg = in_shm.vaddr;


	mutex_lock(&g_smcinvoke_lock);
	mutex_lock(&g_smcinvoke_lock);
	outmsg_size = PAGE_ALIGN(g_max_cb_buf_size);
	outmsg_size = PAGE_ALIGN(g_max_cb_buf_size);
	mutex_unlock(&g_smcinvoke_lock);
	mutex_unlock(&g_smcinvoke_lock);
	out_msg = (void *)__get_free_pages(GFP_KERNEL | __GFP_COMP,
	ret = qtee_shmbridge_allocate_shm(outmsg_size, &out_shm);
						get_order(outmsg_size));
	if (ret) {
	if (!out_msg) {
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto out;
		goto out;
	}
	}
	memset(out_msg, 0, outmsg_size);
	out_msg = out_shm.vaddr;


	ret = marshal_in_invoke_req(&req, args_buf, tzobj->tzhandle, in_msg,
	ret = marshal_in_invoke_req(&req, args_buf, tzobj->tzhandle, in_msg,
			inmsg_size, filp_to_release, tzhandles_to_release);
			inmsg_size, filp_to_release, tzhandles_to_release);
	if (ret)
	if (ret)
		goto out;
		goto out;


	ret = prepare_send_scm_msg(in_msg, inmsg_size, out_msg, outmsg_size,
	ret = prepare_send_scm_msg(in_msg, in_shm.paddr, inmsg_size,
					out_msg, out_shm.paddr, outmsg_size,
					&req, args_buf, &tz_acked);
					&req, args_buf, &tz_acked);


	/*
	/*
@@ -1618,8 +1621,8 @@ static long process_invoke_req(struct file *filp, unsigned int cmd,
	release_filp(filp_to_release, OBJECT_COUNTS_MAX_OO);
	release_filp(filp_to_release, OBJECT_COUNTS_MAX_OO);
	if (ret)
	if (ret)
		release_tzhandles(tzhandles_to_release, OBJECT_COUNTS_MAX_OO);
		release_tzhandles(tzhandles_to_release, OBJECT_COUNTS_MAX_OO);
	free_pages((long)out_msg, get_order(outmsg_size));
	qtee_shmbridge_free_shm(&in_shm);
	free_pages((long)in_msg, get_order(inmsg_size));
	qtee_shmbridge_free_shm(&out_shm);
	kfree(args_buf);
	kfree(args_buf);
	return ret;
	return ret;
}
}
@@ -1698,6 +1701,7 @@ static int smcinvoke_release(struct inode *nodp, struct file *filp)
	struct smcinvoke_file_data *file_data = filp->private_data;
	struct smcinvoke_file_data *file_data = filp->private_data;
	struct smcinvoke_cmd_req req = {0};
	struct smcinvoke_cmd_req req = {0};
	uint32_t tzhandle = 0;
	uint32_t tzhandle = 0;
	struct qtee_shm in_shm = {0}, out_shm = {0};


	if (file_data->context_type == SMCINVOKE_OBJ_TYPE_SERVER) {
	if (file_data->context_type == SMCINVOKE_OBJ_TYPE_SERVER) {
		ret = destroy_cb_server(file_data->server_id);
		ret = destroy_cb_server(file_data->server_id);
@@ -1709,28 +1713,34 @@ static int smcinvoke_release(struct inode *nodp, struct file *filp)
	if (!tzhandle || tzhandle == SMCINVOKE_TZ_ROOT_OBJ)
	if (!tzhandle || tzhandle == SMCINVOKE_TZ_ROOT_OBJ)
		goto out;
		goto out;


	in_buf = (uint8_t *)__get_free_page(GFP_KERNEL | __GFP_COMP);
	ret = qtee_shmbridge_allocate_shm(SMCINVOKE_TZ_MIN_BUF_SIZE, &in_shm);
	out_buf = (uint8_t *)__get_free_page(GFP_KERNEL | __GFP_COMP);
	if (ret) {
	if (!in_buf || !out_buf) {
		ret = -ENOMEM;
		goto out;
	}

	ret = qtee_shmbridge_allocate_shm(SMCINVOKE_TZ_MIN_BUF_SIZE, &out_shm);
	if (ret) {
		ret = -ENOMEM;
		ret = -ENOMEM;
		goto out;
		goto out;
	}
	}


	memset(in_buf, 0, PAGE_SIZE);
	in_buf = in_shm.vaddr;
	memset(out_buf, 0, PAGE_SIZE);
	out_buf = out_shm.vaddr;
	hdr.tzhandle = tzhandle;
	hdr.tzhandle = tzhandle;
	hdr.op = OBJECT_OP_RELEASE;
	hdr.op = OBJECT_OP_RELEASE;
	hdr.counts = 0;
	hdr.counts = 0;
	*(struct smcinvoke_msg_hdr *)in_buf = hdr;
	*(struct smcinvoke_msg_hdr *)in_buf = hdr;


	ret = prepare_send_scm_msg(in_buf, SMCINVOKE_TZ_MIN_BUF_SIZE, out_buf,
	ret = prepare_send_scm_msg(in_buf, in_shm.paddr,
		SMCINVOKE_TZ_MIN_BUF_SIZE, out_buf, out_shm.paddr,
		SMCINVOKE_TZ_MIN_BUF_SIZE, &req, NULL, &release_handles);
		SMCINVOKE_TZ_MIN_BUF_SIZE, &req, NULL, &release_handles);


	process_piggyback_data(out_buf, SMCINVOKE_TZ_MIN_BUF_SIZE);
	process_piggyback_data(out_buf, SMCINVOKE_TZ_MIN_BUF_SIZE);
out:
out:
	kfree(filp->private_data);
	kfree(filp->private_data);
	free_page((long)in_buf);
	qtee_shmbridge_free_shm(&in_shm);
	free_page((long)out_buf);
	qtee_shmbridge_free_shm(&out_shm);


	return ret;
	return ret;
}
}