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

Commit 7bc7640a authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "shmbridge: create bridge over multiple NS VMIDs"

parents 96a83b8f 6233b006
Loading
Loading
Loading
Loading
+36 −24
Original line number Diff line number Diff line
@@ -13,7 +13,6 @@
#include <soc/qcom/scm.h>
#include <soc/qcom/qseecomi.h>
#include <soc/qcom/qtee_shmbridge.h>
#include <soc/qcom/secure_buffer.h>

#define DEFAULT_BRIDGE_SIZE	SZ_4M	/*4M*/
/*
@@ -52,19 +51,26 @@
	TZ_SYSCALL_CREATE_PARAM_ID_1( \
	TZ_SYSCALL_PARAM_TYPE_VAL)

#define MAXSHMVMS 4
#define PERM_BITS 3
#define VM_BITS 16
#define SELF_OWNER_BIT 1
#define SHM_NUM_VM_SHIFT 9
#define SHM_VM_MASK 0xFFFF
#define SHM_PERM_MASK 0x7

#define VM_PERM_R PERM_READ
#define VM_PERM_W PERM_WRITE

/* ns_vmids = ns_vmid as destination number is only 1 */
#define UPDATE_NS_VMIDS(ns_vmid)	((uint64_t)(ns_vmid))
/* ns_vmids */
#define UPDATE_NS_VMIDS(ns_vmids, id)	\
				(((uint64_t)(ns_vmids) << VM_BITS) \
				| ((uint64_t)(id) & SHM_VM_MASK))

/* ns_perms = ns_vm_perm as destination number is only 1 */
#define UPDATE_NS_PERMS(ns_vm_perm)	((uint64_t)(ns_vm_perm))
/* ns_perms */
#define UPDATE_NS_PERMS(ns_perms, perm)	\
				(((uint64_t)(ns_perms) << PERM_BITS) \
				| ((uint64_t)(perm) & SHM_PERM_MASK))

/* pfn_and_ns_perm_flags = paddr | ns_perms */
#define UPDATE_PFN_AND_NS_PERM_FLAGS(paddr, ns_perms)	\
@@ -106,7 +112,7 @@ static int32_t qtee_shmbridge_enable(bool enable)
	desc.arginfo = TZ_SHM_BRIDGE_ENABLE_PARAM_ID;
	ret = scm_call2(TZ_SHM_BRIDGE_ENABLE, &desc);
	if (ret) {
		pr_err("Failed to enable shmbridge, rsp = %d, ret = %d\n",
		pr_err("Failed to enable shmbridge, rsp = %lld, ret = %d\n",
			desc.ret[0], ret);
		return -EINVAL;
	}
@@ -126,40 +132,44 @@ EXPORT_SYMBOL(qtee_shmbridge_is_enabled);
int32_t qtee_shmbridge_register(
		phys_addr_t paddr,
		size_t size,
		uint32_t ns_vmid,
		uint32_t ns_vm_perm,
		uint32_t *ns_vmid_list,
		uint32_t *ns_vm_perm_list,
		uint32_t ns_vmid_num,
		uint32_t tz_perm,
		uint64_t *handle)

{
	int32_t ret = 0;
	uint64_t ns_perms = 0;
	uint64_t destnum = 1;
	uint64_t ns_vmids = 0;
	struct scm_desc desc = {0};
	int i = 0;

	if (!handle) {
		pr_err("shmb handle pointer is NULL\n");
	if (!handle || !ns_vmid_list || !ns_vm_perm_list ||
				ns_vmid_num > MAXSHMVMS) {
		pr_err("invalid input parameters\n");
		return -EINVAL;
	}
	pr_debug("%s: paddr %lx, size %zu, ns_vmid %x, ns_vm_perm %x, ns_perms %s, tz_perm %x\n",
			__func__, (uint64_t)paddr, size, ns_vmid,
			ns_vm_perm, ns_perms, tz_perm);

	ns_perms = UPDATE_NS_PERMS(ns_vm_perm);
	for (i = 0; i < ns_vmid_num; i++) {
		ns_perms = UPDATE_NS_PERMS(ns_perms, ns_vm_perm_list[i]);
		ns_vmids = UPDATE_NS_VMIDS(ns_vmids, ns_vmid_list[i]);
	}

	desc.arginfo = TZ_SHM_BRIDGE_CREATE_PARAM_ID;
	desc.args[0] = UPDATE_PFN_AND_NS_PERM_FLAGS(paddr, ns_perms);
	desc.args[1] = UPDATE_IPFN_AND_S_PERM_FLAGS(paddr, tz_perm);
	desc.args[2] = UPDATE_SIZE_AND_FLAGS(size, destnum);
	desc.args[3] = UPDATE_NS_VMIDS(ns_vmid);
	desc.args[2] = UPDATE_SIZE_AND_FLAGS(size, ns_vmid_num);
	desc.args[3] = ns_vmids;

	pr_debug("%s: arginfo %lx, desc.args[0] %lx, args[1] %lx, args[2] %lx, args[3] %lx\n",
	pr_debug("%s: arginfo %x, desc.args[0] %llx, args[1] %llx, args[2] %llx, args[3] %llx\n",
			__func__, desc.arginfo, desc.args[0],
			desc.args[1], desc.args[2], desc.args[3]);
	ret = scm_call2(TZ_SHM_BRIDGE_CREATE, &desc);
	if (ret || desc.ret[0]) {
		pr_err("create shmbridge failed, ret = %d, status = %x\n",
		pr_err("create shmbridge failed, ret = %d, status = %llx\n",
				ret, desc.ret[0]);
		return ret;
		return -EINVAL;
	}
	*handle = desc.ret[1];
	return 0;
@@ -191,7 +201,7 @@ int32_t qtee_shmbridge_allocate_shm(size_t size, struct qtee_shm *shm)
	unsigned long va;

	if (size > DEFAULT_BRIDGE_SIZE) {
		pr_err("requestd size %zu is larger than bridge size %zu\n",
		pr_err("requestd size %zu is larger than bridge size %d\n",
			size, DEFAULT_BRIDGE_SIZE);
		ret = -EINVAL;
		goto exit;
@@ -216,7 +226,7 @@ int32_t qtee_shmbridge_allocate_shm(size_t size, struct qtee_shm *shm)
	shm->paddr = gen_pool_virt_to_phys(default_bridge.genpool, va);
	shm->size = size;

	pr_debug("%s: shm->paddr %lx, size %zu\n",
	pr_debug("%s: shm->paddr %llx, size %zu\n",
			__func__, (uint64_t)shm->paddr, shm->size);

exit:
@@ -242,6 +252,8 @@ EXPORT_SYMBOL(qtee_shmbridge_free_shm);
static int __init qtee_shmbridge_init(void)
{
	int ret = 0;
	uint32_t ns_vm_ids[] = {VMID_HLOS};
	uint32_t ns_vm_perms[] = {VM_PERM_R|VM_PERM_W};

	if (default_bridge.vaddr) {
		pr_warn("qtee shmbridge is already initialized\n");
@@ -264,8 +276,8 @@ static int __init qtee_shmbridge_init(void)

	/*register default bridge*/
	ret = qtee_shmbridge_register(default_bridge.paddr,
			default_bridge.size, VMID_HLOS,
			VM_PERM_R|VM_PERM_W, VM_PERM_R|VM_PERM_W,
			default_bridge.size, ns_vm_ids,
			ns_vm_perms, 1, VM_PERM_R|VM_PERM_W,
			&default_bridge.handle);
	if (ret) {
		pr_err("Failed to register default bridge, size %zu\n",
+17 −12
Original line number Diff line number Diff line
@@ -6,6 +6,9 @@
#ifndef __QTEE_SHMBRIDGE_H__
#define __QTEE_SHMBRIDGE_H__

/* VMID and permission definitions */
#include <soc/qcom/secure_buffer.h>

/**
 * struct qtee_shm - info of shared memory allocated from the default bridge
 * @ paddr: physical address of the shm allocated from the default bridge
@@ -28,27 +31,29 @@ bool qtee_shmbridge_is_enabled(void);
/**
 * Register paddr & size as a bridge, get bridge handle
 *
 * @ paddr: paddr of buffer to be turned into bridge
 * @ size: size of the bridge
 * @ ns_vmid: non-secure vmid, like VMID_HLOS
 * @ ns_vm_perm: NS VM permission, like PERM_READ, PERM_WRITE
 * @ tz_perm: TZ permission
 * @ *handle: output shmbridge handle
 * @ [IN] addr: paddr of buffer to be turned into bridge
 * @ [IN] size: size of the bridge
 * @ [IN] ns_vmid_list: non-secure vmids array
 * @ [IN] ns_vm_perm_list: NS VM permission array
 * @ [IN] ns_vmid_num: number of NS VMIDs (at most 4)
 * @ [IN] tz_perm: TZ permission
 * @ [OUT] *handle: output shmbridge handle
 *
 * return success or error
 */
int32_t qtee_shmbridge_register(
		phys_addr_t paddr,
		size_t size,
		uint32_t ns_vmid,
		uint32_t ns_vm_perm,
		uint32_t *ns_vmid_list,
		uint32_t *ns_vm_perm_list,
		uint32_t ns_vmid_num,
		uint32_t tz_perm,
		uint64_t *handle);

/**
 * Deregister bridge
 *
 * @ handle: shmbridge handle
 * @ [IN] handle: shmbridge handle
 *
 * return success or error
 */
@@ -57,8 +62,8 @@ int32_t qtee_shmbridge_deregister(uint64_t handle);
/**
 * Sub-allocate from default kernel bridge created by shmb driver
 *
 * @ size: size of the buffer to be sub-allocated from the bridge
 * @ *shm: output qtee_shm structure with buffer paddr, vaddr and
 * @ [IN] size: size of the buffer to be sub-allocated from the bridge
 * @ [OUT] *shm: output qtee_shm structure with buffer paddr, vaddr and
 *         size; returns ERR_PTR or NULL otherwise
 *
 * return success or error
@@ -68,7 +73,7 @@ int32_t qtee_shmbridge_allocate_shm(size_t size, struct qtee_shm *shm);
/*
 * Free buffer that is sub-allocated from default kernel bridge
 *
 * @ shm: qtee_shm structure to be freed
 * @ [IN] shm: qtee_shm structure to be freed
 *
 */
void qtee_shmbridge_free_shm(struct qtee_shm *shm);