drivers/misc/optee: Add SMC backend for arm archs
So far NuttX has supported OP-TEE interfacing over local and RPMsg sockets. This commit introduces support for direct invocation of OP-TEE through arm SMCs. The SMC transport is enabled through CONFIG_DEV_OPTEE_SMC. This SMC implementation has been tested only with arm64, OP-TEE rev 4.4. Note that it does not support reverse direction RPCs, i.e. from the Secure World to the Normal World to something like optee supplicant. A basic RPC handling skeleton is provided with implementation for some basic functions (alloc/free mem, and foreign interrupts) but no supplicant command handling. (+one minor change s/parm/param in arch/arm64/include/syscall to satisfy the spellchecker during PR) Signed-off-by: George Poulios <gpoulios@census-labs.com>
This commit is contained in:
parent
a2b8c9d1d8
commit
b103a64a87
6 changed files with 873 additions and 4 deletions
|
|
@ -110,6 +110,50 @@
|
||||||
#define ARM_SMCC_RES_A6 (6)
|
#define ARM_SMCC_RES_A6 (6)
|
||||||
#define ARM_SMCC_RES_A7 (7)
|
#define ARM_SMCC_RES_A7 (7)
|
||||||
|
|
||||||
|
#define ARM_SMCCC_STD_CALL 0UL
|
||||||
|
#define ARM_SMCCC_FAST_CALL 1UL
|
||||||
|
#define ARM_SMCCC_TYPE_SHIFT 31
|
||||||
|
|
||||||
|
#define ARM_SMCCC_SMC_32 0
|
||||||
|
#define ARM_SMCCC_SMC_64 1
|
||||||
|
#define ARM_SMCCC_CALL_CONV_SHIFT 30
|
||||||
|
|
||||||
|
#define ARM_SMCCC_OWNER_MASK 0x3F
|
||||||
|
#define ARM_SMCCC_OWNER_SHIFT 24
|
||||||
|
|
||||||
|
#define ARM_SMCCC_FUNC_MASK 0xFFFF
|
||||||
|
|
||||||
|
#define ARM_SMCCC_IS_FAST_CALL(smc_val) \
|
||||||
|
((smc_val) & (ARM_SMCCC_FAST_CALL << ARM_SMCCC_TYPE_SHIFT))
|
||||||
|
#define ARM_SMCCC_IS_64(smc_val) \
|
||||||
|
((smc_val) & (ARM_SMCCC_SMC_64 << ARM_SMCCC_CALL_CONV_SHIFT))
|
||||||
|
#define ARM_SMCCC_FUNC_NUM(smc_val) ((smc_val) & ARM_SMCCC_FUNC_MASK)
|
||||||
|
#define ARM_SMCCC_OWNER_NUM(smc_val) \
|
||||||
|
(((smc_val) >> ARM_SMCCC_OWNER_SHIFT) & ARM_SMCCC_OWNER_MASK)
|
||||||
|
|
||||||
|
#define ARM_SMCCC_CALL_VAL(type, calling_convention, owner, func_num) \
|
||||||
|
(((type) << ARM_SMCCC_TYPE_SHIFT) | \
|
||||||
|
((calling_convention) << ARM_SMCCC_CALL_CONV_SHIFT) | \
|
||||||
|
(((owner) & ARM_SMCCC_OWNER_MASK) << ARM_SMCCC_OWNER_SHIFT) | \
|
||||||
|
((func_num) & ARM_SMCCC_FUNC_MASK))
|
||||||
|
|
||||||
|
#define ARM_SMCCC_OWNER_ARCH 0
|
||||||
|
#define ARM_SMCCC_OWNER_CPU 1
|
||||||
|
#define ARM_SMCCC_OWNER_SIP 2
|
||||||
|
#define ARM_SMCCC_OWNER_OEM 3
|
||||||
|
#define ARM_SMCCC_OWNER_STANDARD 4
|
||||||
|
#define ARM_SMCCC_OWNER_TRUSTED_APP 48
|
||||||
|
#define ARM_SMCCC_OWNER_TRUSTED_APP_END 49
|
||||||
|
#define ARM_SMCCC_OWNER_TRUSTED_OS 50
|
||||||
|
#define ARM_SMCCC_OWNER_TRUSTED_OS_END 63
|
||||||
|
|
||||||
|
#define ARM_SMCCC_QUIRK_NONE 0
|
||||||
|
#define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */
|
||||||
|
|
||||||
|
#define ARM_SMCCC_ARCH_FEATURES 0x80000001
|
||||||
|
|
||||||
|
#define ARM_SMCCC_RET_NOT_SUPPORTED ((unsigned long)-1)
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|
@ -300,10 +344,10 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
|
||||||
|
|
||||||
/* semihosting(SMH) call with call number and one parameter */
|
/* semihosting(SMH) call with call number and one parameter */
|
||||||
|
|
||||||
static inline long smh_call(unsigned int nbr, void *parm)
|
static inline long smh_call(unsigned int nbr, void *param)
|
||||||
{
|
{
|
||||||
register uint64_t reg0 __asm__("x0") = (uint64_t)(nbr);
|
register uint64_t reg0 __asm__("x0") = (uint64_t)(nbr);
|
||||||
register uint64_t reg1 __asm__("x1") = (uint64_t)(parm);
|
register uint64_t reg1 __asm__("x1") = (uint64_t)(param);
|
||||||
|
|
||||||
__asm__ __volatile__
|
__asm__ __volatile__
|
||||||
(
|
(
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,11 @@ endif()
|
||||||
|
|
||||||
if(NOT CONFIG_DEV_OPTEE_NONE)
|
if(NOT CONFIG_DEV_OPTEE_NONE)
|
||||||
list(APPEND SRCS optee.c)
|
list(APPEND SRCS optee.c)
|
||||||
list(APPEND SRCS optee_socket.c)
|
if(CONFIG_DEV_OPTEE_SMC)
|
||||||
|
list(APPEND SRCS optee_smc.c)
|
||||||
|
else()
|
||||||
|
list(APPEND SRCS optee_socket.c)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_GOLDFISH_PIPE)
|
if(CONFIG_GOLDFISH_PIPE)
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,12 @@ config DEV_OPTEE_RPMSG
|
||||||
depends on LIBC_MEMFD_SHMFS
|
depends on LIBC_MEMFD_SHMFS
|
||||||
depends on ALLOW_BSD_COMPONENTS
|
depends on ALLOW_BSD_COMPONENTS
|
||||||
|
|
||||||
|
config DEV_OPTEE_SMC
|
||||||
|
bool "OP-TEE SMC CC Support"
|
||||||
|
depends on ARCH_ARM || ARCH_ARM64
|
||||||
|
depends on LIBC_MEMFD_SHMFS
|
||||||
|
depends on ALLOW_BSD_COMPONENTS
|
||||||
|
|
||||||
config DEV_OPTEE_NONE
|
config DEV_OPTEE_NONE
|
||||||
bool "Disable OP-TEE driver"
|
bool "Disable OP-TEE driver"
|
||||||
|
|
||||||
|
|
@ -75,6 +81,26 @@ config OPTEE_REMOTE_CPU_NAME
|
||||||
|
|
||||||
endif # DEV_OPTEE_RPMSG
|
endif # DEV_OPTEE_RPMSG
|
||||||
|
|
||||||
|
if DEV_OPTEE_SMC
|
||||||
|
|
||||||
|
choice
|
||||||
|
prompt "Select OP-TEE conduit method"
|
||||||
|
default DEV_OPTEE_SMC_CONDUIT_SMC
|
||||||
|
---help---
|
||||||
|
Select between the 2 supported conduit methods for invoking the secure
|
||||||
|
world: SMC (when running at EL1) and HVC (when running at EL2, which is
|
||||||
|
not supported by NuttX yet).
|
||||||
|
|
||||||
|
config DEV_OPTEE_SMC_CONDUIT_SMC
|
||||||
|
bool "Use SMC calls to invoke OP-TEE"
|
||||||
|
|
||||||
|
config DEV_OPTEE_SMC_CONDUIT_HVC
|
||||||
|
bool "Use HVC calls to invoke OP-TEE"
|
||||||
|
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
endif # DEV_OPTEE_SMC
|
||||||
|
|
||||||
config DRVR_MKRD
|
config DRVR_MKRD
|
||||||
bool "RAM disk wrapper (mkrd)"
|
bool "RAM disk wrapper (mkrd)"
|
||||||
default n
|
default n
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,11 @@ endif
|
||||||
|
|
||||||
ifneq ($(CONFIG_DEV_OPTEE_NONE),y)
|
ifneq ($(CONFIG_DEV_OPTEE_NONE),y)
|
||||||
CSRCS += optee.c
|
CSRCS += optee.c
|
||||||
CSRCS += optee_socket.c
|
ifeq ($(CONFIG_DEV_OPTEE_SMC),y)
|
||||||
|
CSRCS += optee_smc.c
|
||||||
|
else
|
||||||
|
CSRCS += optee_socket.c
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_GOLDFISH_PIPE),y)
|
ifeq ($(CONFIG_GOLDFISH_PIPE),y)
|
||||||
|
|
|
||||||
343
drivers/misc/optee_smc.c
Normal file
343
drivers/misc/optee_smc.c
Normal file
|
|
@ -0,0 +1,343 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* drivers/misc/optee_smc.c
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "optee.h"
|
||||||
|
#include "optee_smc.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if defined(CONFIG_ARCH_ARM)
|
||||||
|
# define smccc_smc arm_smccc_smc
|
||||||
|
# define smccc_hvc arm_smccc_hvc
|
||||||
|
# define smccc_res_t arm_smccc_res_t
|
||||||
|
#elif defined(CONFIG_ARCH_ARM64)
|
||||||
|
# define smccc_smc arm64_smccc_smc
|
||||||
|
# define smccc_hvc arm64_smccc_hvc
|
||||||
|
# define smccc_res_t arm64_smccc_res_t
|
||||||
|
#else
|
||||||
|
# error "CONFIG_DEV_OPTEE_SMC is only supported on arm and arm64"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEV_OPTEE_SMC_CONDUIT_SMC
|
||||||
|
# define smc_conduit smccc_smc
|
||||||
|
#else
|
||||||
|
# define smc_conduit smccc_hvc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
typedef void (*optee_smc_fn)(unsigned long, unsigned long, unsigned long,
|
||||||
|
unsigned long, unsigned long, unsigned long,
|
||||||
|
unsigned long, unsigned long,
|
||||||
|
FAR smccc_res_t *);
|
||||||
|
|
||||||
|
struct optee_smc_priv_data
|
||||||
|
{
|
||||||
|
struct optee_priv_data base;
|
||||||
|
optee_smc_fn smc_fn;
|
||||||
|
};
|
||||||
|
|
||||||
|
union optee_smc_os_revision
|
||||||
|
{
|
||||||
|
smccc_res_t smccc;
|
||||||
|
struct optee_smc_call_get_os_revision_result result;
|
||||||
|
};
|
||||||
|
|
||||||
|
union optee_smc_calls_revision
|
||||||
|
{
|
||||||
|
smccc_res_t smccc;
|
||||||
|
struct optee_smc_calls_revision_result result;
|
||||||
|
};
|
||||||
|
|
||||||
|
union optee_smc_exchg_caps
|
||||||
|
{
|
||||||
|
smccc_res_t smccc;
|
||||||
|
struct optee_smc_exchange_capabilities_result result;
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static inline uintptr_t reg_pair_to_uintptr(uint64_t reg0, uint64_t reg1)
|
||||||
|
{
|
||||||
|
return (uintptr_t)(reg0 << 32 | (reg1 & UINT32_MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void reg_pair_from_64(uint64_t val, uint64_t *reg0,
|
||||||
|
uint64_t *reg1)
|
||||||
|
{
|
||||||
|
*reg0 = val >> 32;
|
||||||
|
*reg1 = val & UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool optee_smc_is_compatible(optee_smc_fn smc_fn)
|
||||||
|
{
|
||||||
|
union optee_smc_os_revision osrev;
|
||||||
|
union optee_smc_calls_revision callsrev;
|
||||||
|
union optee_smc_exchg_caps xchgcaps;
|
||||||
|
smccc_res_t callsuid;
|
||||||
|
|
||||||
|
/* Print the OS revision and build ID (if reported) */
|
||||||
|
|
||||||
|
osrev.result.build_id = 0;
|
||||||
|
|
||||||
|
smc_fn(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0, &osrev.smccc);
|
||||||
|
|
||||||
|
if (osrev.result.build_id)
|
||||||
|
{
|
||||||
|
syslog(LOG_INFO, "OP-TEE: OS revision %lu.%lu (%08lx)\n",
|
||||||
|
osrev.result.major, osrev.result.minor,
|
||||||
|
osrev.result.build_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
syslog(LOG_INFO, "OP-TEE: OS revision %lu.%lu\n",
|
||||||
|
osrev.result.major, osrev.result.minor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the API UID */
|
||||||
|
|
||||||
|
smc_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &callsuid);
|
||||||
|
|
||||||
|
if (callsuid.a0 != OPTEE_MSG_UID_0 || callsuid.a1 != OPTEE_MSG_UID_1 ||
|
||||||
|
callsuid.a2 != OPTEE_MSG_UID_2 || callsuid.a3 != OPTEE_MSG_UID_3)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "OP-TEE: API UID mismatch\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the API revision */
|
||||||
|
|
||||||
|
smc_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &callsrev.smccc);
|
||||||
|
|
||||||
|
if (callsrev.result.major != OPTEE_MSG_REVISION_MAJOR ||
|
||||||
|
callsrev.result.minor < OPTEE_MSG_REVISION_MINOR)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "OP-TEE: API revision incompatible\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the capabilities */
|
||||||
|
|
||||||
|
smc_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES, OPTEE_SMC_NSEC_CAP_UNIPROCESSOR,
|
||||||
|
0, 0, 0, 0, 0, 0, &xchgcaps.smccc);
|
||||||
|
|
||||||
|
if (xchgcaps.result.status != OPTEE_SMC_RETURN_OK)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "OP-TEE: Failed to exchange capabilities\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(xchgcaps.result.capabilities & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM))
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "OP-TEE: Does not support dynamic shared mem\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void optee_smc_handle_rpc(FAR struct optee_priv_data *priv_,
|
||||||
|
FAR smccc_res_t *par)
|
||||||
|
{
|
||||||
|
FAR struct optee_shm_entry *shme;
|
||||||
|
uintptr_t shme_pa;
|
||||||
|
uint32_t rpc_func;
|
||||||
|
|
||||||
|
rpc_func = OPTEE_SMC_RETURN_GET_RPC_FUNC(par->a0);
|
||||||
|
par->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
|
||||||
|
|
||||||
|
switch (rpc_func)
|
||||||
|
{
|
||||||
|
case OPTEE_SMC_RPC_FUNC_ALLOC:
|
||||||
|
if (!optee_shm_alloc(priv_, NULL, par->a1,
|
||||||
|
TEE_SHM_ALLOC | TEE_SHM_REGISTER, &shme))
|
||||||
|
{
|
||||||
|
shme_pa = optee_va_to_pa((FAR void *)(uintptr_t)shme->shm.addr);
|
||||||
|
reg_pair_from_64(shme_pa, &par->a1, &par->a2);
|
||||||
|
reg_pair_from_64((uintptr_t)shme, &par->a4, &par->a5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reg_pair_from_64(0, &par->a1, &par->a2);
|
||||||
|
reg_pair_from_64(0, &par->a4, &par->a5);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTEE_SMC_RPC_FUNC_FREE:
|
||||||
|
shme = (FAR struct optee_shm_entry *)
|
||||||
|
reg_pair_to_uintptr(par->a1, par->a2);
|
||||||
|
optee_shm_free(priv_, shme);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
syslog(LOG_ERR, "OP-TEE: RPC 0x%04x not implemented\n", rpc_func);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: optee_transport_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform any initialization actions specific to the transport used
|
||||||
|
* right before the driver is registered.
|
||||||
|
*
|
||||||
|
* Returned Values:
|
||||||
|
* 0 on success; A negated errno value is returned on any failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int optee_transport_init(void)
|
||||||
|
{
|
||||||
|
if (!optee_smc_is_compatible(smc_conduit))
|
||||||
|
{
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: optee_transport_open
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform any transport-specific actions upon driver character device
|
||||||
|
* open.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* priv_ - the optee_priv_data struct to allocate and return by
|
||||||
|
* reference.
|
||||||
|
*
|
||||||
|
* Returned Values:
|
||||||
|
* 0 on success; A negated errno value is returned on any failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int optee_transport_open(FAR struct optee_priv_data **priv_)
|
||||||
|
{
|
||||||
|
FAR struct optee_smc_priv_data *priv;
|
||||||
|
|
||||||
|
priv = kmm_zalloc(sizeof(struct optee_smc_priv_data));
|
||||||
|
if (priv == NULL)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->base.alignment = OPTEE_MSG_NONCONTIG_PAGE_SIZE;
|
||||||
|
priv->smc_fn = smc_conduit;
|
||||||
|
*priv_ = (FAR struct optee_priv_data *)priv;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: optee_transport_close
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform any transport-specific actions upon driver character device
|
||||||
|
* close.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* priv_ - the optee_priv_data struct to close and de-allocate.
|
||||||
|
*
|
||||||
|
* Returned Values:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void optee_transport_close(FAR struct optee_priv_data *priv_)
|
||||||
|
{
|
||||||
|
kmm_free(priv_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: optee_transport_call
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Call OP-TEE OS using SMCs.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* priv_ - the optee_priv_data struct to use
|
||||||
|
*
|
||||||
|
* Returned Values:
|
||||||
|
* 0 on success; A negated errno value is returned on any failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int optee_transport_call(FAR struct optee_priv_data *priv_,
|
||||||
|
FAR struct optee_msg_arg *arg)
|
||||||
|
{
|
||||||
|
FAR struct optee_smc_priv_data *priv =
|
||||||
|
(FAR struct optee_smc_priv_data *)priv_;
|
||||||
|
smccc_res_t res;
|
||||||
|
smccc_res_t par;
|
||||||
|
uintptr_t arg_pa;
|
||||||
|
|
||||||
|
memset(&par, 0, sizeof(smccc_res_t));
|
||||||
|
|
||||||
|
par.a0 = OPTEE_SMC_CALL_WITH_ARG;
|
||||||
|
arg_pa = optee_va_to_pa(arg);
|
||||||
|
reg_pair_from_64(arg_pa, &par.a1, &par.a2);
|
||||||
|
|
||||||
|
for (; ; )
|
||||||
|
{
|
||||||
|
memset(&res, 0, sizeof(smccc_res_t));
|
||||||
|
|
||||||
|
priv->smc_fn(par.a0, par.a1, par.a2, par.a3,
|
||||||
|
par.a4, par.a5, par.a6, par.a7, &res);
|
||||||
|
|
||||||
|
if (OPTEE_SMC_RETURN_IS_RPC(res.a0))
|
||||||
|
{
|
||||||
|
memcpy(&par, &res, 4 * sizeof(unsigned long));
|
||||||
|
optee_smc_handle_rpc(priv_, &par);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (int)res.a0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
448
drivers/misc/optee_smc.h
Normal file
448
drivers/misc/optee_smc.h
Normal file
|
|
@ -0,0 +1,448 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* drivers/misc/optee_smc.h
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
* Copyright (c) 2015-2018, Linaro Limited
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __DRIVERS_MISC_OPTEE_SMC_H
|
||||||
|
#define __DRIVERS_MISC_OPTEE_SMC_H
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <arch/syscall.h>
|
||||||
|
#include <nuttx/bits.h>
|
||||||
|
|
||||||
|
/* This file is based on
|
||||||
|
* https://github.com
|
||||||
|
* /OP-TEE/optee_os/blob/master/core/arch/arm/include/sm/optee_smc.h
|
||||||
|
* and may need to be updated when introducing new features.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OPTEE_SMC_STD_CALL_VAL(func_num) \
|
||||||
|
ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_32, \
|
||||||
|
ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
|
||||||
|
#define OPTEE_SMC_FAST_CALL_VAL(func_num) \
|
||||||
|
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
|
||||||
|
ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
|
||||||
|
|
||||||
|
/* Function specified by SMC Calling convention.
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_FUNCID_CALLS_COUNT 0xFF00
|
||||||
|
#define OPTEE_SMC_CALLS_COUNT \
|
||||||
|
ARM_SMCCC_CALL_VAL(OPTEE_SMC_FAST_CALL, SMCCC_SMC_32, \
|
||||||
|
SMCCC_OWNER_TRUSTED_OS_END, \
|
||||||
|
OPTEE_SMC_FUNCID_CALLS_COUNT)
|
||||||
|
|
||||||
|
/* Normal cached memory (write-back), shareable for SMP systems and not
|
||||||
|
* shareable for UP systems.
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_SHM_CACHED 1
|
||||||
|
|
||||||
|
/* a0..a7 is used as register names in the descriptions below, on arm32
|
||||||
|
* that translates to r0..r7 and on arm64 to w0..w7. In both cases it's
|
||||||
|
* 32-bit registers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Function specified by SMC Calling convention
|
||||||
|
*
|
||||||
|
* Return one of the following UIDs if using API specified in this file
|
||||||
|
* without further extensions:
|
||||||
|
* 65cb6b93-af0c-4617-8ed6-644a8d1140f8
|
||||||
|
* see also OPTEE_SMC_UID_* in optee_msg.h
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID
|
||||||
|
#define OPTEE_SMC_CALLS_UID \
|
||||||
|
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
|
||||||
|
ARM_SMCCC_OWNER_TRUSTED_OS_END, \
|
||||||
|
OPTEE_SMC_FUNCID_CALLS_UID)
|
||||||
|
|
||||||
|
/* Function specified by SMC Calling convention
|
||||||
|
*
|
||||||
|
* Returns 2.0 if using API specified in this file without further
|
||||||
|
* extensions. See also OPTEE_MSG_REVISION_* in optee_msg.h
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION
|
||||||
|
#define OPTEE_SMC_CALLS_REVISION \
|
||||||
|
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
|
||||||
|
ARM_SMCCC_OWNER_TRUSTED_OS_END, \
|
||||||
|
OPTEE_SMC_FUNCID_CALLS_REVISION)
|
||||||
|
|
||||||
|
struct optee_smc_calls_revision_result
|
||||||
|
{
|
||||||
|
unsigned long major;
|
||||||
|
unsigned long minor;
|
||||||
|
unsigned long reserved0;
|
||||||
|
unsigned long reserved1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Get UUID of Trusted OS.
|
||||||
|
*
|
||||||
|
* Used by non-secure world to figure out which Trusted OS is installed.
|
||||||
|
* Note that returned UUID is the UUID of the Trusted OS, not of the API.
|
||||||
|
*
|
||||||
|
* Returns UUID in a0-4 in the same way as OPTEE_SMC_CALLS_UID
|
||||||
|
* described above.
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID
|
||||||
|
#define OPTEE_SMC_CALL_GET_OS_UUID \
|
||||||
|
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_UUID)
|
||||||
|
|
||||||
|
/* Get revision of Trusted OS.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Returns revision in a0-1 in the same way as OPTEE_SMC_CALLS_REVISION
|
||||||
|
* described above. May optionally return a 32-bit build identifier in a2,
|
||||||
|
* with zero meaning unspecified.
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION
|
||||||
|
#define OPTEE_SMC_CALL_GET_OS_REVISION \
|
||||||
|
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_REVISION)
|
||||||
|
|
||||||
|
struct optee_smc_call_get_os_revision_result
|
||||||
|
{
|
||||||
|
unsigned long major;
|
||||||
|
unsigned long minor;
|
||||||
|
unsigned long build_id;
|
||||||
|
unsigned long reserved1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Call with struct optee_msg_arg as argument
|
||||||
|
*
|
||||||
|
* Call register usage:
|
||||||
|
* a0 SMC Function ID, OPTEE_SMC*CALL_WITH_ARG
|
||||||
|
* a1 Upper 32bit of a 64bit physical pointer to a struct optee_msg_arg
|
||||||
|
* a2 Lower 32bit of a 64bit physical pointer to a struct optee_msg_arg
|
||||||
|
* a3 Cache settings, not used if physical pointer is in a predefined shared
|
||||||
|
* memory area else per OPTEE_SMC_SHM_*
|
||||||
|
* a4-6 Not used
|
||||||
|
* a7 Hypervisor Client ID register
|
||||||
|
*
|
||||||
|
* Normal return register usage:
|
||||||
|
* a0 Return value, OPTEE_SMC_RETURN_*
|
||||||
|
* a1-3 Not used
|
||||||
|
* a4-7 Preserved
|
||||||
|
*
|
||||||
|
* OPTEE_SMC_RETURN_ETHREAD_LIMIT return register usage:
|
||||||
|
* a0 Return value, OPTEE_SMC_RETURN_ETHREAD_LIMIT
|
||||||
|
* a1-3 Preserved
|
||||||
|
* a4-7 Preserved
|
||||||
|
*
|
||||||
|
* RPC return register usage:
|
||||||
|
* a0 Return value, OPTEE_SMC_RETURN_IS_RPC(val)
|
||||||
|
* a1-2 RPC parameters
|
||||||
|
* a3-7 Resume information, must be preserved
|
||||||
|
*
|
||||||
|
* Possible return values:
|
||||||
|
* OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this
|
||||||
|
* function.
|
||||||
|
* OPTEE_SMC_RETURN_OK Call completed, result updated in
|
||||||
|
* the previously supplied struct
|
||||||
|
* optee_msg_arg.
|
||||||
|
* OPTEE_SMC_RETURN_ETHREAD_LIMIT Number of Trusted OS threads exceeded,
|
||||||
|
* try again later.
|
||||||
|
* OPTEE_SMC_RETURN_EBADADDR Bad physical pointer to struct
|
||||||
|
* optee_msg_arg.
|
||||||
|
* OPTEE_SMC_RETURN_EBADCMD Bad/unknown cmd in struct optee_msg_arg
|
||||||
|
* OPTEE_SMC_RETURN_IS_RPC() Call suspended by RPC call to normal
|
||||||
|
* world.
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG
|
||||||
|
#define OPTEE_SMC_CALL_WITH_ARG \
|
||||||
|
OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_ARG)
|
||||||
|
|
||||||
|
/* Get Shared Memory Config
|
||||||
|
*
|
||||||
|
* Returns the Secure/Non-secure shared memory config.
|
||||||
|
*
|
||||||
|
* Call register usage:
|
||||||
|
* a0 SMC Function ID, OPTEE_SMC_GET_SHM_CONFIG
|
||||||
|
* a1-6 Not used
|
||||||
|
* a7 Hypervisor Client ID register
|
||||||
|
*
|
||||||
|
* Have config return register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_OK
|
||||||
|
* a1 Physical address of start of SHM
|
||||||
|
* a2 Size of of SHM
|
||||||
|
* a3 Cache settings of memory, as defined by the
|
||||||
|
* OPTEE_SMC_SHM_* values above
|
||||||
|
* a4-7 Preserved
|
||||||
|
*
|
||||||
|
* Not available register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_ENOTAVAIL
|
||||||
|
* a1-3 Not used
|
||||||
|
* a4-7 Preserved
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_FUNCID_GET_SHM_CONFIG 7
|
||||||
|
#define OPTEE_SMC_GET_SHM_CONFIG \
|
||||||
|
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SHM_CONFIG)
|
||||||
|
|
||||||
|
struct optee_smc_get_shm_config_result
|
||||||
|
{
|
||||||
|
unsigned long status;
|
||||||
|
unsigned long start;
|
||||||
|
unsigned long size;
|
||||||
|
unsigned long settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Exchanges capabilities between normal world and secure world
|
||||||
|
*
|
||||||
|
* Call register usage:
|
||||||
|
* a0 SMC Function ID, OPTEE_SMC_EXCHANGE_CAPABILITIES
|
||||||
|
* a1 bitfield of normal world capabilities OPTEE_SMC_NSEC_CAP_*
|
||||||
|
* a2-6 Not used
|
||||||
|
* a7 Hypervisor Client ID register
|
||||||
|
*
|
||||||
|
* Normal return register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_OK
|
||||||
|
* a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
|
||||||
|
* a2-7 Preserved
|
||||||
|
*
|
||||||
|
* Error return register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal
|
||||||
|
* world
|
||||||
|
* a1 bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
|
||||||
|
* a2-7 Preserved
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Normal world works as a uniprocessor system */
|
||||||
|
#define OPTEE_SMC_NSEC_CAP_UNIPROCESSOR BIT(0)
|
||||||
|
/* Secure world has reserved shared memory for normal world to use */
|
||||||
|
#define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM BIT(0)
|
||||||
|
/* Secure world can communicate via previously unregistered shared memory */
|
||||||
|
#define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM BIT(1)
|
||||||
|
|
||||||
|
/* Secure world supports commands "register/unregister shared memory",
|
||||||
|
* secure world accepts command buffers located in any parts of non-secure
|
||||||
|
* RAM
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_SEC_CAP_DYNAMIC_SHM BIT(2)
|
||||||
|
|
||||||
|
#define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9
|
||||||
|
#define OPTEE_SMC_EXCHANGE_CAPABILITIES \
|
||||||
|
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES)
|
||||||
|
|
||||||
|
struct optee_smc_exchange_capabilities_result
|
||||||
|
{
|
||||||
|
unsigned long status;
|
||||||
|
unsigned long capabilities;
|
||||||
|
unsigned long reserved0;
|
||||||
|
unsigned long reserved1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Disable and empties cache of shared memory objects
|
||||||
|
*
|
||||||
|
* Secure world can cache frequently used shared memory objects, for
|
||||||
|
* example objects used as RPC arguments. When secure world is idle this
|
||||||
|
* function returns one shared memory reference to free. To disable the
|
||||||
|
* cache and free all cached objects this function has to be called until
|
||||||
|
* it returns OPTEE_SMC_RETURN_ENOTAVAIL.
|
||||||
|
*
|
||||||
|
* Call register usage:
|
||||||
|
* a0 SMC Function ID, OPTEE_SMC_DISABLE_SHM_CACHE
|
||||||
|
* a1-6 Not used
|
||||||
|
* a7 Hypervisor Client ID register
|
||||||
|
*
|
||||||
|
* Normal return register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_OK
|
||||||
|
* a1 Upper 32bit of a 64bit Shared memory cookie
|
||||||
|
* a2 Lower 32bit of a 64bit Shared memory cookie
|
||||||
|
* a3-7 Preserved
|
||||||
|
*
|
||||||
|
* Cache empty return register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_ENOTAVAIL
|
||||||
|
* a1-7 Preserved
|
||||||
|
*
|
||||||
|
* Not idle return register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_EBUSY
|
||||||
|
* a1-7 Preserved
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE 10
|
||||||
|
#define OPTEE_SMC_DISABLE_SHM_CACHE \
|
||||||
|
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE)
|
||||||
|
|
||||||
|
struct optee_smc_disable_shm_cache_result
|
||||||
|
{
|
||||||
|
unsigned long status;
|
||||||
|
unsigned long shm_upper32;
|
||||||
|
unsigned long shm_lower32;
|
||||||
|
unsigned long reserved0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Enable cache of shared memory objects
|
||||||
|
*
|
||||||
|
* Secure world can cache frequently used shared memory objects, for
|
||||||
|
* example objects used as RPC arguments. When secure world is idle this
|
||||||
|
* function returns OPTEE_SMC_RETURN_OK and the cache is enabled. If
|
||||||
|
* secure world isn't idle OPTEE_SMC_RETURN_EBUSY is returned.
|
||||||
|
*
|
||||||
|
* Call register usage:
|
||||||
|
* a0 SMC Function ID, OPTEE_SMC_ENABLE_SHM_CACHE
|
||||||
|
* a1-6 Not used
|
||||||
|
* a7 Hypervisor Client ID register
|
||||||
|
*
|
||||||
|
* Normal return register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_OK
|
||||||
|
* a1-7 Preserved
|
||||||
|
*
|
||||||
|
* Not idle return register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_EBUSY
|
||||||
|
* a1-7 Preserved
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE 11
|
||||||
|
#define OPTEE_SMC_ENABLE_SHM_CACHE \
|
||||||
|
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE)
|
||||||
|
|
||||||
|
/* Resume from RPC (for example after processing a foreign interrupt)
|
||||||
|
*
|
||||||
|
* Call register usage:
|
||||||
|
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC
|
||||||
|
* a1-3 Value of a1-3 when OPTEE_SMC_CALL_WITH_ARG returned
|
||||||
|
* OPTEE_SMC_RETURN_RPC in a0
|
||||||
|
*
|
||||||
|
* Return register usage is the same as for OPTEE_SMC_*CALL_WITH_ARG above.
|
||||||
|
*
|
||||||
|
* Possible return values
|
||||||
|
* OPTEE_SMC_RETURN_UNKNOWN_FUNCTION Trusted OS does not recognize this
|
||||||
|
* function.
|
||||||
|
* OPTEE_SMC_RETURN_OK Original call completed, result
|
||||||
|
* updated in the previously supplied.
|
||||||
|
* struct optee_msg_arg
|
||||||
|
* OPTEE_SMC_RETURN_RPC Call suspended by RPC call to normal
|
||||||
|
* world.
|
||||||
|
* OPTEE_SMC_RETURN_ERESUME Resume failed, the opaque resume
|
||||||
|
* information was corrupt.
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_FUNCID_RETURN_FROM_RPC 3
|
||||||
|
#define OPTEE_SMC_CALL_RETURN_FROM_RPC \
|
||||||
|
OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_RETURN_FROM_RPC)
|
||||||
|
|
||||||
|
#define OPTEE_SMC_RETURN_RPC_PREFIX_MASK 0xFFFF0000
|
||||||
|
#define OPTEE_SMC_RETURN_RPC_PREFIX 0xFFFF0000
|
||||||
|
#define OPTEE_SMC_RETURN_RPC_FUNC_MASK 0x0000FFFF
|
||||||
|
|
||||||
|
#define OPTEE_SMC_RETURN_GET_RPC_FUNC(ret) \
|
||||||
|
((ret) & OPTEE_SMC_RETURN_RPC_FUNC_MASK)
|
||||||
|
|
||||||
|
#define OPTEE_SMC_RPC_VAL(func) ((func) | OPTEE_SMC_RETURN_RPC_PREFIX)
|
||||||
|
|
||||||
|
/* Allocate memory for RPC parameter passing. The memory is used to hold a
|
||||||
|
* struct optee_msg_arg.
|
||||||
|
*
|
||||||
|
* "Call" register usage:
|
||||||
|
* a0 This value, OPTEE_SMC_RETURN_RPC_ALLOC
|
||||||
|
* a1 Size in bytes of required argument memory
|
||||||
|
* a2 Not used
|
||||||
|
* a3 Resume information, must be preserved
|
||||||
|
* a4-5 Not used
|
||||||
|
* a6-7 Resume information, must be preserved
|
||||||
|
*
|
||||||
|
* "Return" register usage:
|
||||||
|
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
|
||||||
|
* a1 Upper 32bits of 64bit physical pointer to allocated
|
||||||
|
* memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
|
||||||
|
* be allocated.
|
||||||
|
* a2 Lower 32bits of 64bit physical pointer to allocated
|
||||||
|
* memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
|
||||||
|
* be allocated
|
||||||
|
* a3 Preserved
|
||||||
|
* a4 Upper 32bits of 64bit Shared memory cookie used when freeing
|
||||||
|
* the memory or doing an RPC
|
||||||
|
* a5 Lower 32bits of 64bit Shared memory cookie used when freeing
|
||||||
|
* the memory or doing an RPC
|
||||||
|
* a6-7 Preserved
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_RPC_FUNC_ALLOC 0
|
||||||
|
#define OPTEE_SMC_RETURN_RPC_ALLOC \
|
||||||
|
OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_ALLOC)
|
||||||
|
|
||||||
|
/* Free memory previously allocated by OPTEE_SMC_RETURN_RPC_ALLOC
|
||||||
|
*
|
||||||
|
* "Call" register usage:
|
||||||
|
* a0 This value, OPTEE_SMC_RETURN_RPC_FREE
|
||||||
|
* a1 Upper 32bits of 64bit shared memory cookie belonging to this
|
||||||
|
* argument memory
|
||||||
|
* a2 Lower 32bits of 64bit shared memory cookie belonging to this
|
||||||
|
* argument memory
|
||||||
|
* a3-7 Resume information, must be preserved
|
||||||
|
*
|
||||||
|
* "Return" register usage:
|
||||||
|
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
|
||||||
|
* a1-2 Not used
|
||||||
|
* a3-7 Preserved
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_RPC_FUNC_FREE 2
|
||||||
|
#define OPTEE_SMC_RETURN_RPC_FREE \
|
||||||
|
OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE)
|
||||||
|
|
||||||
|
/* Deliver foreign interrupt to normal world.
|
||||||
|
*
|
||||||
|
* "Call" register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
|
||||||
|
* a1-7 Resume information, must be preserved
|
||||||
|
*
|
||||||
|
* "Return" register usage:
|
||||||
|
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
|
||||||
|
* a1-7 Preserved
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4
|
||||||
|
#define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \
|
||||||
|
OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR)
|
||||||
|
|
||||||
|
/* Do an RPC request. The supplied struct optee_msg_arg tells which
|
||||||
|
* request to do and the parameters for the request. The following fields
|
||||||
|
* are used (the rest are unused):
|
||||||
|
* - cmd the Request ID
|
||||||
|
* - ret return value of the request, filled in by normal world
|
||||||
|
* - num_params number of parameters for the request
|
||||||
|
* - params the parameters
|
||||||
|
* - param_attrs attributes of the parameters
|
||||||
|
*
|
||||||
|
* "Call" register usage:
|
||||||
|
* a0 OPTEE_SMC_RETURN_RPC_CMD
|
||||||
|
* a1 Upper 32bit of a 64bit Shared memory cookie holding a
|
||||||
|
* struct optee_msg_arg, must be preserved, only the data should
|
||||||
|
* be updated
|
||||||
|
* a2 Lower 32bit of a 64bit Shared memory cookie holding a
|
||||||
|
* struct optee_msg_arg, must be preserved, only the data should
|
||||||
|
* be updated
|
||||||
|
* a3-7 Resume information, must be preserved
|
||||||
|
*
|
||||||
|
* "Return" register usage:
|
||||||
|
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
|
||||||
|
* a1-2 Not used
|
||||||
|
* a3-7 Preserved
|
||||||
|
*/
|
||||||
|
#define OPTEE_SMC_RPC_FUNC_CMD 5
|
||||||
|
#define OPTEE_SMC_RETURN_RPC_CMD \
|
||||||
|
OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_CMD)
|
||||||
|
|
||||||
|
/* Returned in a0 */
|
||||||
|
#define OPTEE_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF
|
||||||
|
|
||||||
|
/* Returned in a0 only from Trusted OS functions */
|
||||||
|
#define OPTEE_SMC_RETURN_OK 0x0
|
||||||
|
#define OPTEE_SMC_RETURN_ETHREAD_LIMIT 0x1
|
||||||
|
#define OPTEE_SMC_RETURN_EBUSY 0x2
|
||||||
|
#define OPTEE_SMC_RETURN_ERESUME 0x3
|
||||||
|
#define OPTEE_SMC_RETURN_EBADADDR 0x4
|
||||||
|
#define OPTEE_SMC_RETURN_EBADCMD 0x5
|
||||||
|
#define OPTEE_SMC_RETURN_ENOMEM 0x6
|
||||||
|
#define OPTEE_SMC_RETURN_ENOTAVAIL 0x7
|
||||||
|
#define OPTEE_SMC_RETURN_IS_RPC(ret) optee_smc_return_is_rpc((ret))
|
||||||
|
|
||||||
|
static inline bool optee_smc_return_is_rpc(uint32_t ret)
|
||||||
|
{
|
||||||
|
return ret != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION &&
|
||||||
|
(ret & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) ==
|
||||||
|
OPTEE_SMC_RETURN_RPC_PREFIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __DRIVERS_MISC_OPTEE_SMC_H */
|
||||||
Loading…
Add table
Reference in a new issue