Commit 4615e5a3 authored by Jens Wiklander's avatar Jens Wiklander

optee: add FF-A support

Adds support for using FF-A [1] as transport to the OP-TEE driver.

Introduces struct optee_msg_param_fmem which carries all information
needed when OP-TEE is calling FFA_MEM_RETRIEVE_REQ to get the shared
memory reference mapped by the hypervisor in S-EL2. Register usage is
also updated to include the information needed.

The FF-A part of this driver is enabled if CONFIG_ARM_FFA_TRANSPORT is
enabled.

[1] https://developer.arm.com/documentation/den0077/latestAcked-by: default avatarSumit Garg <sumit.garg@linaro.org>
Signed-off-by: default avatarJens Wiklander <jens.wiklander@linaro.org>
parent c51a564a
......@@ -6,6 +6,7 @@ optee-objs += rpc.o
optee-objs += supp.o
optee-objs += device.o
optee-objs += smc_abi.o
optee-objs += ffa_abi.o
# for tracing framework to find optee_trace.h
CFLAGS_smc_abi.o := -I$(src)
......@@ -107,11 +107,20 @@ static struct optee_session *find_session(struct optee_context_data *ctxdata,
struct tee_shm *optee_get_msg_arg(struct tee_context *ctx, size_t num_params,
struct optee_msg_arg **msg_arg)
{
struct optee *optee = tee_get_drvdata(ctx->teedev);
size_t sz = OPTEE_MSG_GET_ARG_SIZE(num_params);
struct tee_shm *shm;
struct optee_msg_arg *ma;
shm = tee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params),
TEE_SHM_MAPPED | TEE_SHM_PRIV);
/*
* rpc_arg_count is set to the number of allocated parameters in
* the RPC argument struct if a second MSG arg struct is expected.
* The second arg struct will then be used for RPC.
*/
if (optee->rpc_arg_count)
sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count);
shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
if (IS_ERR(shm))
return shm;
......
......@@ -172,6 +172,9 @@ void optee_remove_common(struct optee *optee)
mutex_destroy(&optee->call_queue.mutex);
}
static int smc_abi_rc;
static int ffa_abi_rc;
static int optee_core_init(void)
{
/*
......@@ -184,13 +187,22 @@ static int optee_core_init(void)
if (is_kdump_kernel())
return -ENODEV;
return optee_smc_abi_register();
smc_abi_rc = optee_smc_abi_register();
ffa_abi_rc = optee_ffa_abi_register();
/* If both failed there's no point with this module */
if (smc_abi_rc && ffa_abi_rc)
return smc_abi_rc;
return 0;
}
module_init(optee_core_init);
static void optee_core_exit(void)
{
optee_smc_abi_unregister();
if (!smc_abi_rc)
optee_smc_abi_unregister();
if (!ffa_abi_rc)
optee_ffa_abi_unregister();
}
module_exit(optee_core_exit);
......
This diff is collapsed.
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2019-2021, Linaro Limited
*/
/*
* This file is exported by OP-TEE and is kept in sync between secure world
* and normal world drivers. We're using ARM FF-A 1.0 specification.
*/
#ifndef __OPTEE_FFA_H
#define __OPTEE_FFA_H
#include <linux/arm_ffa.h>
/*
* Normal world sends requests with FFA_MSG_SEND_DIRECT_REQ and
* responses are returned with FFA_MSG_SEND_DIRECT_RESP for normal
* messages.
*
* All requests with FFA_MSG_SEND_DIRECT_REQ and FFA_MSG_SEND_DIRECT_RESP
* are using the AArch32 SMC calling convention with register usage as
* defined in FF-A specification:
* w0: Function ID (0x8400006F or 0x84000070)
* w1: Source/Destination IDs
* w2: Reserved (MBZ)
* w3-w7: Implementation defined, free to be used below
*/
#define OPTEE_FFA_VERSION_MAJOR 1
#define OPTEE_FFA_VERSION_MINOR 0
#define OPTEE_FFA_BLOCKING_CALL(id) (id)
#define OPTEE_FFA_YIELDING_CALL_BIT 31
#define OPTEE_FFA_YIELDING_CALL(id) ((id) | BIT(OPTEE_FFA_YIELDING_CALL_BIT))
/*
* Returns the API version implemented, currently follows the FF-A version.
* Call register usage:
* w3: Service ID, OPTEE_FFA_GET_API_VERSION
* w4-w7: Not used (MBZ)
*
* Return register usage:
* w3: OPTEE_FFA_VERSION_MAJOR
* w4: OPTEE_FFA_VERSION_MINOR
* w5-w7: Not used (MBZ)
*/
#define OPTEE_FFA_GET_API_VERSION OPTEE_FFA_BLOCKING_CALL(0)
/*
* Returns the revision of OP-TEE.
*
* Used by non-secure world to figure out which version of the Trusted OS
* is installed. Note that the returned revision is the revision of the
* Trusted OS, not of the API.
*
* Call register usage:
* w3: Service ID, OPTEE_FFA_GET_OS_VERSION
* w4-w7: Unused (MBZ)
*
* Return register usage:
* w3: CFG_OPTEE_REVISION_MAJOR
* w4: CFG_OPTEE_REVISION_MINOR
* w5: TEE_IMPL_GIT_SHA1 (or zero if not supported)
*/
#define OPTEE_FFA_GET_OS_VERSION OPTEE_FFA_BLOCKING_CALL(1)
/*
* Exchange capabilities between normal world and secure world.
*
* Currently there are no defined capabilities. When features are added new
* capabilities may be added.
*
* Call register usage:
* w3: Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES
* w4-w7: Note used (MBZ)
*
* Return register usage:
* w3: Error code, 0 on success
* w4: Bit[7:0]: Number of parameters needed for RPC to be supplied
* as the second MSG arg struct for
* OPTEE_FFA_YIELDING_CALL_WITH_ARG.
* Bit[31:8]: Reserved (MBZ)
* w5-w7: Note used (MBZ)
*/
#define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
/*
* Unregister shared memory
*
* Call register usage:
* w3: Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM
* w4: Shared memory handle, lower bits
* w5: Shared memory handle, higher bits
* w6-w7: Not used (MBZ)
*
* Return register usage:
* w3: Error code, 0 on success
* w4-w7: Note used (MBZ)
*/
#define OPTEE_FFA_UNREGISTER_SHM OPTEE_FFA_BLOCKING_CALL(3)
/*
* Call with struct optee_msg_arg as argument in the supplied shared memory
* with a zero internal offset and normal cached memory attributes.
* Register usage:
* w3: Service ID, OPTEE_FFA_YIELDING_CALL_WITH_ARG
* w4: Lower 32 bits of a 64-bit Shared memory handle
* w5: Upper 32 bits of a 64-bit Shared memory handle
* w6: Offset into shared memory pointing to a struct optee_msg_arg
* right after the parameters of this struct (at offset
* OPTEE_MSG_GET_ARG_SIZE(num_params) follows a struct optee_msg_arg
* for RPC, this struct has reserved space for the number of RPC
* parameters as returned by OPTEE_FFA_EXCHANGE_CAPABILITIES.
* w7: Not used (MBZ)
* Resume from RPC. Register usage:
* w3: Service ID, OPTEE_FFA_YIELDING_CALL_RESUME
* w4-w6: Not used (MBZ)
* w7: Resume info
*
* Normal return (yielding call is completed). Register usage:
* w3: Error code, 0 on success
* w4: OPTEE_FFA_YIELDING_CALL_RETURN_DONE
* w5-w7: Not used (MBZ)
*
* RPC interrupt return (RPC from secure world). Register usage:
* w3: Error code == 0
* w4: Any defined RPC code but OPTEE_FFA_YIELDING_CALL_RETURN_DONE
* w5-w6: Not used (MBZ)
* w7: Resume info
*
* Possible error codes in register w3:
* 0: Success
* FFA_DENIED: w4 isn't one of OPTEE_FFA_YIELDING_CALL_START
* OPTEE_FFA_YIELDING_CALL_RESUME
*
* Possible error codes for OPTEE_FFA_YIELDING_CALL_START,
* FFA_BUSY: Number of OP-TEE OS threads exceeded,
* try again later
* FFA_DENIED: RPC shared memory object not found
* FFA_INVALID_PARAMETER: Bad shared memory handle or offset into the memory
*
* Possible error codes for OPTEE_FFA_YIELDING_CALL_RESUME
* FFA_INVALID_PARAMETER: Bad resume info
*/
#define OPTEE_FFA_YIELDING_CALL_WITH_ARG OPTEE_FFA_YIELDING_CALL(0)
#define OPTEE_FFA_YIELDING_CALL_RESUME OPTEE_FFA_YIELDING_CALL(1)
#define OPTEE_FFA_YIELDING_CALL_RETURN_DONE 0
#define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD 1
#define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT 2
#endif /*__OPTEE_FFA_H*/
......@@ -28,6 +28,9 @@
#define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT 0x5
#define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT 0x6
#define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT 0x7
#define OPTEE_MSG_ATTR_TYPE_FMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
#define OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT
#define OPTEE_MSG_ATTR_TYPE_FMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT
#define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 0x9
#define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT 0xa
#define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT 0xb
......@@ -96,6 +99,8 @@
*/
#define OPTEE_MSG_NONCONTIG_PAGE_SIZE 4096
#define OPTEE_MSG_FMEM_INVALID_GLOBAL_ID 0xffffffffffffffff
/**
* struct optee_msg_param_tmem - temporary memory reference parameter
* @buf_ptr: Address of the buffer
......@@ -127,6 +132,23 @@ struct optee_msg_param_rmem {
u64 shm_ref;
};
/**
* struct optee_msg_param_fmem - ffa memory reference parameter
* @offs_lower: Lower bits of offset into shared memory reference
* @offs_upper: Upper bits of offset into shared memory reference
* @internal_offs: Internal offset into the first page of shared memory
* reference
* @size: Size of the buffer
* @global_id: Global identifier of Shared memory
*/
struct optee_msg_param_fmem {
u32 offs_low;
u16 offs_high;
u16 internal_offs;
u64 size;
u64 global_id;
};
/**
* struct optee_msg_param_value - opaque value parameter
*
......@@ -143,13 +165,15 @@ struct optee_msg_param_value {
* @attr: attributes
* @tmem: parameter by temporary memory reference
* @rmem: parameter by registered memory reference
* @fmem: parameter by ffa registered memory reference
* @value: parameter by opaque value
* @octets: parameter by octet string
*
* @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
* the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value or octets,
* OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
* OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem,
* OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_FMEM_* indicates
* @rmem or @fmem depending on the conduit.
* OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
*/
struct optee_msg_param {
......@@ -157,6 +181,7 @@ struct optee_msg_param {
union {
struct optee_msg_param_tmem tmem;
struct optee_msg_param_rmem rmem;
struct optee_msg_param_fmem fmem;
struct optee_msg_param_value value;
u8 octets[24];
} u;
......
......@@ -7,6 +7,7 @@
#define OPTEE_PRIVATE_H
#include <linux/arm-smccc.h>
#include <linux/rhashtable.h>
#include <linux/semaphore.h>
#include <linux/tee_drv.h>
#include <linux/types.h>
......@@ -22,6 +23,7 @@
#define TEEC_ERROR_NOT_SUPPORTED 0xFFFF000A
#define TEEC_ERROR_COMMUNICATION 0xFFFF000E
#define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C
#define TEEC_ERROR_BUSY 0xFFFF000D
#define TEEC_ERROR_SHORT_BUFFER 0xFFFF0010
#define TEEC_ORIGIN_COMMS 0x00000002
......@@ -73,19 +75,28 @@ struct optee_supp {
struct completion reqs_c;
};
/**
* struct optee_smc - SMC ABI specifics
* @invoke_fn: function to issue smc or hvc
* @memremaped_shm virtual address of memory in shared memory pool
* @sec_caps: secure world capabilities defined by
* OPTEE_SMC_SEC_CAP_* in optee_smc.h
*/
struct optee_smc {
optee_invoke_fn *invoke_fn;
void *memremaped_shm;
u32 sec_caps;
};
/**
* struct optee_ffa_data - FFA communication struct
* @ffa_dev FFA device, contains the destination id, the id of
* OP-TEE in secure world
* @ffa_ops FFA operations
* @mutex Serializes access to @global_ids
* @global_ids FF-A shared memory global handle translation
*/
struct optee_ffa {
struct ffa_device *ffa_dev;
const struct ffa_dev_ops *ffa_ops;
/* Serializes access to @global_ids */
struct mutex mutex;
struct rhashtable global_ids;
};
struct optee;
/**
......@@ -116,11 +127,13 @@ struct optee_ops {
* world
* @teedev: client device
* @smc: specific to SMC ABI
* @ffa: specific to FF-A ABI
* @call_queue: queue of threads waiting to call @invoke_fn
* @wait_queue: queue of threads from secure world waiting for a
* secure world sync object
* @supp: supplicant synchronization struct for RPC to supplicant
* @pool: shared memory pool
* @rpc_arg_count: If > 0 number of RPC parameters to make room for
* @scan_bus_done flag if device registation was already done.
* @scan_bus_wq workqueue to scan optee bus and register optee drivers
* @scan_bus_work workq to scan optee bus and register optee drivers
......@@ -129,11 +142,15 @@ struct optee {
struct tee_device *supp_teedev;
struct tee_device *teedev;
const struct optee_ops *ops;
struct optee_smc smc;
union {
struct optee_smc smc;
struct optee_ffa ffa;
};
struct optee_call_queue call_queue;
struct optee_wait_queue wait_queue;
struct optee_supp supp;
struct tee_shm_pool *pool;
unsigned int rpc_arg_count;
bool scan_bus_done;
struct workqueue_struct *scan_bus_wq;
struct work_struct scan_bus_work;
......@@ -266,5 +283,7 @@ static inline void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val)
/* Registration of the ABIs */
int optee_smc_abi_register(void);
void optee_smc_abi_unregister(void);
int optee_ffa_abi_register(void);
void optee_ffa_abi_unregister(void);
#endif /*OPTEE_PRIVATE_H*/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment