arm-trusted-firmware/include/lib/smccc.h
Olivier Deprez 0fe7b9f2bc feat: pass SMCCCv1.3 SVE hint bit to dispatchers
SMCCCv1.3 introduces the SVE hint bit added to the SMC FID (bit 16)
denoting that the world issuing an SMC doesn't expect the callee to
preserve the SVE state (FFR, predicates, Zn vector bits greater than
127). Update the generic SMC handler to copy the SVE hint bit state
to SMC flags and mask out the bit by default for the services called
by the standard dispatcher. It is permitted by the SMCCC standard to
ignore the bit as long as the SVE state is preserved. In any case a
callee must preserve the NEON state (FPCR/FPSR, Vn 128b vectors)
whichever the SVE hint bit state.

Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Change-Id: I2b163ed83dc311b8f81f96b23c942829ae9fa1b5
2022-11-08 09:28:36 +01:00

226 lines
7.6 KiB
C

/*
* Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef SMCCC_H
#define SMCCC_H
#include <lib/utils_def.h>
#define SMCCC_VERSION_MAJOR_SHIFT U(16)
#define SMCCC_VERSION_MAJOR_MASK U(0x7FFF)
#define SMCCC_VERSION_MINOR_SHIFT U(0)
#define SMCCC_VERSION_MINOR_MASK U(0xFFFF)
#define MAKE_SMCCC_VERSION(_major, _minor) \
((((uint32_t)(_major) & SMCCC_VERSION_MAJOR_MASK) << \
SMCCC_VERSION_MAJOR_SHIFT) \
| (((uint32_t)(_minor) & SMCCC_VERSION_MINOR_MASK) << \
SMCCC_VERSION_MINOR_SHIFT))
#define SMCCC_MAJOR_VERSION U(1)
#define SMCCC_MINOR_VERSION U(2)
/*******************************************************************************
* Bit definitions inside the function id as per the SMC calling convention
******************************************************************************/
#define FUNCID_TYPE_SHIFT U(31)
#define FUNCID_TYPE_MASK U(0x1)
#define FUNCID_TYPE_WIDTH U(1)
#define FUNCID_CC_SHIFT U(30)
#define FUNCID_CC_MASK U(0x1)
#define FUNCID_CC_WIDTH U(1)
#define FUNCID_OEN_SHIFT U(24)
#define FUNCID_OEN_MASK U(0x3f)
#define FUNCID_OEN_WIDTH U(6)
#define FUNCID_SVE_HINT_SHIFT U(16)
#define FUNCID_SVE_HINT_MASK U(1)
#define FUNCID_SVE_HINT_WIDTH U(1)
#define FUNCID_NUM_SHIFT U(0)
#define FUNCID_NUM_MASK U(0xffff)
#define FUNCID_NUM_WIDTH U(16)
#define FUNCID_MASK U(0xffffffff)
#define GET_SMC_NUM(id) (((id) >> FUNCID_NUM_SHIFT) & \
FUNCID_NUM_MASK)
#define GET_SMC_TYPE(id) (((id) >> FUNCID_TYPE_SHIFT) & \
FUNCID_TYPE_MASK)
#define GET_SMC_CC(id) (((id) >> FUNCID_CC_SHIFT) & \
FUNCID_CC_MASK)
#define GET_SMC_OEN(id) (((id) >> FUNCID_OEN_SHIFT) & \
FUNCID_OEN_MASK)
/*******************************************************************************
* SMCCC_ARCH_SOC_ID SoC version & revision bit definition
******************************************************************************/
#define SOC_ID_JEP_106_BANK_IDX_MASK GENMASK_32(30, 24)
#define SOC_ID_JEP_106_BANK_IDX_SHIFT U(24)
#define SOC_ID_JEP_106_ID_CODE_MASK GENMASK_32(23, 16)
#define SOC_ID_JEP_106_ID_CODE_SHIFT U(16)
#define SOC_ID_IMPL_DEF_MASK GENMASK_32(15, 0)
#define SOC_ID_IMPL_DEF_SHIFT U(0)
#define SOC_ID_SET_JEP_106(bkid, mfid) ((((bkid) << SOC_ID_JEP_106_BANK_IDX_SHIFT) & \
SOC_ID_JEP_106_BANK_IDX_MASK) | \
(((mfid) << SOC_ID_JEP_106_ID_CODE_SHIFT) & \
SOC_ID_JEP_106_ID_CODE_MASK))
#define SOC_ID_REV_MASK GENMASK_32(30, 0)
#define SOC_ID_REV_SHIFT U(0)
/*******************************************************************************
* Owning entity number definitions inside the function id as per the SMC
* calling convention
******************************************************************************/
#define OEN_ARM_START U(0)
#define OEN_ARM_END U(0)
#define OEN_CPU_START U(1)
#define OEN_CPU_END U(1)
#define OEN_SIP_START U(2)
#define OEN_SIP_END U(2)
#define OEN_OEM_START U(3)
#define OEN_OEM_END U(3)
#define OEN_STD_START U(4) /* Standard Service Calls */
#define OEN_STD_END U(4)
#define OEN_STD_HYP_START U(5) /* Standard Hypervisor Service calls */
#define OEN_STD_HYP_END U(5)
#define OEN_VEN_HYP_START U(6) /* Vendor Hypervisor Service calls */
#define OEN_VEN_HYP_END U(6)
#define OEN_TAP_START U(48) /* Trusted Applications */
#define OEN_TAP_END U(49)
#define OEN_TOS_START U(50) /* Trusted OS */
#define OEN_TOS_END U(63)
#define OEN_LIMIT U(64)
/* Flags and error codes */
#define SMC_64 U(1)
#define SMC_32 U(0)
#define SMC_TYPE_FAST UL(1)
#define SMC_TYPE_YIELD UL(0)
#define SMC_OK ULL(0)
#define SMC_UNK -1
#define SMC_PREEMPTED -2 /* Not defined by the SMCCC */
/* Return codes for Arm Architecture Service SMC calls */
#define SMC_ARCH_CALL_SUCCESS 0
#define SMC_ARCH_CALL_NOT_SUPPORTED -1
#define SMC_ARCH_CALL_NOT_REQUIRED -2
#define SMC_ARCH_CALL_INVAL_PARAM -3
/*
* Various flags passed to SMC handlers
*
* Bit 5 and bit 0 of the flag are used to
* determine the source security state as
* follows:
* ---------------------------------
* Bit 5 | Bit 0 | Security state
* ---------------------------------
* 0 0 SMC_FROM_SECURE
* 0 1 SMC_FROM_NON_SECURE
* 1 1 SMC_FROM_REALM
*
* Bit 16 of flags records the caller's SMC
* SVE hint bit according to SMCCCv1.3.
* It can be consumed by dispatchers using
* is_sve_hint_set macro.
*
*/
#define SMC_FROM_SECURE (U(0) << 0)
#define SMC_FROM_NON_SECURE (U(1) << 0)
#define SMC_FROM_REALM U(0x21)
#define SMC_FROM_MASK U(0x21)
#ifndef __ASSEMBLER__
#include <stdint.h>
#include <lib/cassert.h>
#if ENABLE_RME
#define is_caller_non_secure(_f) (((_f) & SMC_FROM_MASK) \
== SMC_FROM_NON_SECURE)
#define is_caller_secure(_f) (((_f) & SMC_FROM_MASK) \
== SMC_FROM_SECURE)
#define is_caller_realm(_f) (((_f) & SMC_FROM_MASK) \
== SMC_FROM_REALM)
#define caller_sec_state(_f) ((_f) & SMC_FROM_MASK)
#else /* ENABLE_RME */
#define is_caller_non_secure(_f) (((_f) & SMC_FROM_NON_SECURE) != U(0))
#define is_caller_secure(_f) (!is_caller_non_secure(_f))
#endif /* ENABLE_RME */
#define is_sve_hint_set(_f) (((_f) & (FUNCID_SVE_HINT_MASK \
<< FUNCID_SVE_HINT_SHIFT)) != U(0))
/* The macro below is used to identify a Standard Service SMC call */
#define is_std_svc_call(_fid) (GET_SMC_OEN(_fid) == OEN_STD_START)
/* The macro below is used to identify a Arm Architectural Service SMC call */
#define is_arm_arch_svc_call(_fid) (GET_SMC_OEN(_fid) == OEN_ARM_START)
/* The macro below is used to identify a valid Fast SMC call */
#define is_valid_fast_smc(_fid) ((!(((_fid) >> 16) & U(0xff))) && \
(GET_SMC_TYPE(_fid) \
== (uint32_t)SMC_TYPE_FAST))
/*
* Macro to define UUID for services. Apart from defining and initializing a
* uuid_t structure, this macro verifies that the first word of the defined UUID
* does not equal SMC_UNK. This is to ensure that the caller won't mistake the
* returned UUID in x0 for an invalid SMC error return
*/
#define DEFINE_SVC_UUID2(_name, _tl, _tm, _th, _cl, _ch, \
_n0, _n1, _n2, _n3, _n4, _n5) \
CASSERT((uint32_t)(_tl) != (uint32_t)SMC_UNK, \
invalid_svc_uuid_##_name); \
static const uuid_t _name = { \
{((_tl) >> 24) & 0xFF, \
((_tl) >> 16) & 0xFF, \
((_tl) >> 8) & 0xFF, \
((_tl) & 0xFF)}, \
{((_tm) >> 8) & 0xFF, \
((_tm) & 0xFF)}, \
{((_th) >> 8) & 0xFF, \
((_th) & 0xFF)}, \
(_cl), (_ch), \
{ (_n0), (_n1), (_n2), (_n3), (_n4), (_n5) } \
}
/*
* Return a UUID in the SMC return registers.
*
* Acccording to section 5.3 of the SMCCC, UUIDs are returned as a single
* 128-bit value using the SMC32 calling convention. This value is mapped to
* argument registers x0-x3 on AArch64 (resp. r0-r3 on AArch32). x0 for example
* shall hold bytes 0 to 3, with byte 0 in the low-order bits.
*/
static inline uint32_t smc_uuid_word(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
{
return ((uint32_t) b0) | (((uint32_t) b1) << 8) |
(((uint32_t) b2) << 16) | (((uint32_t) b3) << 24);
}
#define SMC_UUID_RET(_h, _uuid) \
SMC_RET4(handle, \
smc_uuid_word((_uuid).time_low[0], (_uuid).time_low[1], \
(_uuid).time_low[2], (_uuid).time_low[3]), \
smc_uuid_word((_uuid).time_mid[0], (_uuid).time_mid[1], \
(_uuid).time_hi_and_version[0], \
(_uuid).time_hi_and_version[1]), \
smc_uuid_word((_uuid).clock_seq_hi_and_reserved, \
(_uuid).clock_seq_low, (_uuid).node[0], \
(_uuid).node[1]), \
smc_uuid_word((_uuid).node[2], (_uuid).node[3], \
(_uuid).node[4], (_uuid).node[5]))
#endif /*__ASSEMBLER__*/
#endif /* SMCCC_H */