Browse Source
When the source code says 'SMCC' it is talking about the SMC Calling Convention. The correct acronym is SMCCC. This affects a few definitions and file names. Some files have been renamed (smcc.h, smcc_helpers.h and smcc_macros.S) but the old files have been kept for compatibility, they include the new ones with an ERROR_DEPRECATED guard. Change-Id: I78f94052a502436fdd97ca32c0fe86bd58173f2f Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>pull/1314/head
Antonio Nino Diaz
7 years ago
28 changed files with 617 additions and 558 deletions
@ -1,199 +1,15 @@ |
|||
/* |
|||
* Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. |
|||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
#ifndef __SMCC_MACROS_S__ |
|||
#define __SMCC_MACROS_S__ |
|||
|
|||
#include <arch.h> |
|||
#if !ERROR_DEPRECATED |
|||
#include <smccc_macros.S> |
|||
|
|||
/* |
|||
* Macro to save the General purpose registers (r0 - r12), the banked |
|||
* spsr, lr, sp registers and the `scr` register to the SMC context on entry |
|||
* due a SMC call. The `lr` of the current mode (monitor) is expected to be |
|||
* already saved. The `sp` must point to the `smc_ctx_t` to save to. |
|||
* Additionally, also save the 'pmcr' register as this is updated whilst |
|||
* executing in the secure world. |
|||
*/ |
|||
.macro smcc_save_gp_mode_regs |
|||
/* Save r0 - r12 in the SMC context */ |
|||
stm sp, {r0-r12} |
|||
mov r0, sp |
|||
add r0, r0, #SMC_CTX_SP_USR |
|||
|
|||
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) |
|||
/* Must be in secure state to restore Monitor mode */ |
|||
ldcopr r4, SCR |
|||
bic r2, r4, #SCR_NS_BIT |
|||
stcopr r2, SCR |
|||
isb |
|||
|
|||
cps #MODE32_sys |
|||
stm r0!, {sp, lr} |
|||
|
|||
cps #MODE32_irq |
|||
mrs r2, spsr |
|||
stm r0!, {r2, sp, lr} |
|||
|
|||
cps #MODE32_fiq |
|||
mrs r2, spsr |
|||
stm r0!, {r2, sp, lr} |
|||
|
|||
cps #MODE32_svc |
|||
mrs r2, spsr |
|||
stm r0!, {r2, sp, lr} |
|||
|
|||
cps #MODE32_abt |
|||
mrs r2, spsr |
|||
stm r0!, {r2, sp, lr} |
|||
|
|||
cps #MODE32_und |
|||
mrs r2, spsr |
|||
stm r0!, {r2, sp, lr} |
|||
|
|||
/* lr_mon is already saved by caller */ |
|||
cps #MODE32_mon |
|||
mrs r2, spsr |
|||
stm r0!, {r2} |
|||
|
|||
stcopr r4, SCR |
|||
isb |
|||
#else |
|||
/* Save the banked registers including the current SPSR and LR */ |
|||
mrs r4, sp_usr |
|||
mrs r5, lr_usr |
|||
mrs r6, spsr_irq |
|||
mrs r7, sp_irq |
|||
mrs r8, lr_irq |
|||
mrs r9, spsr_fiq |
|||
mrs r10, sp_fiq |
|||
mrs r11, lr_fiq |
|||
mrs r12, spsr_svc |
|||
stm r0!, {r4-r12} |
|||
|
|||
mrs r4, sp_svc |
|||
mrs r5, lr_svc |
|||
mrs r6, spsr_abt |
|||
mrs r7, sp_abt |
|||
mrs r8, lr_abt |
|||
mrs r9, spsr_und |
|||
mrs r10, sp_und |
|||
mrs r11, lr_und |
|||
mrs r12, spsr |
|||
stm r0!, {r4-r12} |
|||
/* lr_mon is already saved by caller */ |
|||
|
|||
ldcopr r4, SCR |
|||
#endif |
|||
str r4, [sp, #SMC_CTX_SCR] |
|||
ldcopr r4, PMCR |
|||
str r4, [sp, #SMC_CTX_PMCR] |
|||
.endm |
|||
|
|||
/* |
|||
* Macro to restore the `smc_ctx_t`, which includes the General purpose |
|||
* registers and banked mode registers, and exit from the monitor mode. |
|||
* r0 must point to the `smc_ctx_t` to restore from. |
|||
*/ |
|||
.macro monitor_exit |
|||
/* |
|||
* Save the current sp and restore the smc context |
|||
* pointer to sp which will be used for handling the |
|||
* next SMC. |
|||
*/ |
|||
str sp, [r0, #SMC_CTX_SP_MON] |
|||
mov sp, r0 |
|||
|
|||
/* |
|||
* Restore SCR first so that we access the right banked register |
|||
* when the other mode registers are restored. |
|||
*/ |
|||
ldr r1, [r0, #SMC_CTX_SCR] |
|||
stcopr r1, SCR |
|||
isb |
|||
|
|||
/* |
|||
* Restore the PMCR register. |
|||
*/ |
|||
ldr r1, [r0, #SMC_CTX_PMCR] |
|||
stcopr r1, PMCR |
|||
|
|||
/* Restore the banked registers including the current SPSR */ |
|||
add r1, r0, #SMC_CTX_SP_USR |
|||
|
|||
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) |
|||
/* Must be in secure state to restore Monitor mode */ |
|||
ldcopr r4, SCR |
|||
bic r2, r4, #SCR_NS_BIT |
|||
stcopr r2, SCR |
|||
isb |
|||
|
|||
cps #MODE32_sys |
|||
ldm r1!, {sp, lr} |
|||
|
|||
cps #MODE32_irq |
|||
ldm r1!, {r2, sp, lr} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
cps #MODE32_fiq |
|||
ldm r1!, {r2, sp, lr} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
cps #MODE32_svc |
|||
ldm r1!, {r2, sp, lr} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
cps #MODE32_abt |
|||
ldm r1!, {r2, sp, lr} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
cps #MODE32_und |
|||
ldm r1!, {r2, sp, lr} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
cps #MODE32_mon |
|||
ldm r1!, {r2} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
stcopr r4, SCR |
|||
isb |
|||
#else |
|||
ldm r1!, {r4-r12} |
|||
msr sp_usr, r4 |
|||
msr lr_usr, r5 |
|||
msr spsr_irq, r6 |
|||
msr sp_irq, r7 |
|||
msr lr_irq, r8 |
|||
msr spsr_fiq, r9 |
|||
msr sp_fiq, r10 |
|||
msr lr_fiq, r11 |
|||
msr spsr_svc, r12 |
|||
|
|||
ldm r1!, {r4-r12} |
|||
msr sp_svc, r4 |
|||
msr lr_svc, r5 |
|||
msr spsr_abt, r6 |
|||
msr sp_abt, r7 |
|||
msr lr_abt, r8 |
|||
msr spsr_und, r9 |
|||
msr sp_und, r10 |
|||
msr lr_und, r11 |
|||
/* |
|||
* Use the `_fsxc` suffix explicitly to instruct the assembler |
|||
* to update all the 32 bits of SPSR. Else, by default, the |
|||
* assembler assumes `_fc` suffix which only modifies |
|||
* f->[31:24] and c->[7:0] bits of SPSR. |
|||
*/ |
|||
msr spsr_fsxc, r12 |
|||
#define smcc_save_gp_mode_regs smccc_save_gp_mode_regs |
|||
#endif |
|||
|
|||
/* Restore the LR */ |
|||
ldr lr, [r0, #SMC_CTX_LR_MON] |
|||
|
|||
/* Restore the rest of the general purpose registers */ |
|||
ldm r0, {r0-r12} |
|||
eret |
|||
.endm |
|||
|
|||
#endif /* __SMCC_MACROS_S__ */ |
|||
|
@ -0,0 +1,166 @@ |
|||
/*
|
|||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __SMCCC_HELPERS_H__ |
|||
#define __SMCCC_HELPERS_H__ |
|||
|
|||
#include <smccc.h> |
|||
|
|||
/* These are offsets to registers in smc_ctx_t */ |
|||
#define SMC_CTX_GPREG_R0 0x0 |
|||
#define SMC_CTX_GPREG_R1 0x4 |
|||
#define SMC_CTX_GPREG_R2 0x8 |
|||
#define SMC_CTX_GPREG_R3 0xC |
|||
#define SMC_CTX_GPREG_R4 0x10 |
|||
#define SMC_CTX_GPREG_R5 0x14 |
|||
#define SMC_CTX_SP_USR 0x34 |
|||
#define SMC_CTX_SPSR_MON 0x78 |
|||
#define SMC_CTX_SP_MON 0x7C |
|||
#define SMC_CTX_LR_MON 0x80 |
|||
#define SMC_CTX_SCR 0x84 |
|||
#define SMC_CTX_PMCR 0x88 |
|||
#define SMC_CTX_SIZE 0x90 |
|||
|
|||
#ifndef __ASSEMBLY__ |
|||
#include <cassert.h> |
|||
#include <types.h> |
|||
|
|||
/*
|
|||
* The generic structure to save arguments and callee saved registers during |
|||
* an SMC. Also this structure is used to store the result return values after |
|||
* the completion of SMC service. |
|||
*/ |
|||
typedef struct smc_ctx { |
|||
u_register_t r0; |
|||
u_register_t r1; |
|||
u_register_t r2; |
|||
u_register_t r3; |
|||
u_register_t r4; |
|||
u_register_t r5; |
|||
u_register_t r6; |
|||
u_register_t r7; |
|||
u_register_t r8; |
|||
u_register_t r9; |
|||
u_register_t r10; |
|||
u_register_t r11; |
|||
u_register_t r12; |
|||
/* spsr_usr doesn't exist */ |
|||
u_register_t sp_usr; |
|||
u_register_t lr_usr; |
|||
u_register_t spsr_irq; |
|||
u_register_t sp_irq; |
|||
u_register_t lr_irq; |
|||
u_register_t spsr_fiq; |
|||
u_register_t sp_fiq; |
|||
u_register_t lr_fiq; |
|||
u_register_t spsr_svc; |
|||
u_register_t sp_svc; |
|||
u_register_t lr_svc; |
|||
u_register_t spsr_abt; |
|||
u_register_t sp_abt; |
|||
u_register_t lr_abt; |
|||
u_register_t spsr_und; |
|||
u_register_t sp_und; |
|||
u_register_t lr_und; |
|||
u_register_t spsr_mon; |
|||
/*
|
|||
* `sp_mon` will point to the C runtime stack in monitor mode. But prior |
|||
* to exit from SMC, this will point to the `smc_ctx_t` so that |
|||
* on next entry due to SMC, the `smc_ctx_t` can be easily accessed. |
|||
*/ |
|||
u_register_t sp_mon; |
|||
u_register_t lr_mon; |
|||
u_register_t scr; |
|||
u_register_t pmcr; |
|||
/*
|
|||
* The workaround for CVE-2017-5715 requires storing information in |
|||
* the bottom 3 bits of the stack pointer. Add a padding field to |
|||
* force the size of the struct to be a multiple of 8. |
|||
*/ |
|||
u_register_t pad; |
|||
} smc_ctx_t __aligned(8); |
|||
|
|||
/*
|
|||
* Compile time assertions related to the 'smc_context' structure to |
|||
* ensure that the assembler and the compiler view of the offsets of |
|||
* the structure members is the same. |
|||
*/ |
|||
CASSERT(SMC_CTX_GPREG_R0 == __builtin_offsetof(smc_ctx_t, r0), \ |
|||
assert_smc_ctx_greg_r0_offset_mismatch); |
|||
CASSERT(SMC_CTX_GPREG_R1 == __builtin_offsetof(smc_ctx_t, r1), \ |
|||
assert_smc_ctx_greg_r1_offset_mismatch); |
|||
CASSERT(SMC_CTX_GPREG_R2 == __builtin_offsetof(smc_ctx_t, r2), \ |
|||
assert_smc_ctx_greg_r2_offset_mismatch); |
|||
CASSERT(SMC_CTX_GPREG_R3 == __builtin_offsetof(smc_ctx_t, r3), \ |
|||
assert_smc_ctx_greg_r3_offset_mismatch); |
|||
CASSERT(SMC_CTX_GPREG_R4 == __builtin_offsetof(smc_ctx_t, r4), \ |
|||
assert_smc_ctx_greg_r4_offset_mismatch); |
|||
CASSERT(SMC_CTX_SP_USR == __builtin_offsetof(smc_ctx_t, sp_usr), \ |
|||
assert_smc_ctx_sp_usr_offset_mismatch); |
|||
CASSERT(SMC_CTX_LR_MON == __builtin_offsetof(smc_ctx_t, lr_mon), \ |
|||
assert_smc_ctx_lr_mon_offset_mismatch); |
|||
CASSERT(SMC_CTX_SPSR_MON == __builtin_offsetof(smc_ctx_t, spsr_mon), \ |
|||
assert_smc_ctx_spsr_mon_offset_mismatch); |
|||
|
|||
CASSERT((sizeof(smc_ctx_t) & 0x7) == 0, assert_smc_ctx_not_aligned); |
|||
CASSERT(SMC_CTX_SIZE == sizeof(smc_ctx_t), assert_smc_ctx_size_mismatch); |
|||
|
|||
/* Convenience macros to return from SMC handler */ |
|||
#define SMC_RET0(_h) { \ |
|||
return (uintptr_t)(_h); \ |
|||
} |
|||
#define SMC_RET1(_h, _r0) { \ |
|||
((smc_ctx_t *)(_h))->r0 = (_r0); \ |
|||
SMC_RET0(_h); \ |
|||
} |
|||
#define SMC_RET2(_h, _r0, _r1) { \ |
|||
((smc_ctx_t *)(_h))->r1 = (_r1); \ |
|||
SMC_RET1(_h, (_r0)); \ |
|||
} |
|||
#define SMC_RET3(_h, _r0, _r1, _r2) { \ |
|||
((smc_ctx_t *)(_h))->r2 = (_r2); \ |
|||
SMC_RET2(_h, (_r0), (_r1)); \ |
|||
} |
|||
#define SMC_RET4(_h, _r0, _r1, _r2, _r3) { \ |
|||
((smc_ctx_t *)(_h))->r3 = (_r3); \ |
|||
SMC_RET3(_h, (_r0), (_r1), (_r2)); \ |
|||
} |
|||
|
|||
/* Return a UUID in the SMC return registers */ |
|||
#define SMC_UUID_RET(_h, _uuid) \ |
|||
SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \ |
|||
((const uint32_t *) &(_uuid))[1], \ |
|||
((const uint32_t *) &(_uuid))[2], \ |
|||
((const uint32_t *) &(_uuid))[3]) |
|||
|
|||
/*
|
|||
* Helper macro to retrieve the SMC parameters from smc_ctx_t. |
|||
*/ |
|||
#define get_smc_params_from_ctx(_hdl, _r1, _r2, _r3, _r4) { \ |
|||
_r1 = ((smc_ctx_t *)_hdl)->r1; \ |
|||
_r2 = ((smc_ctx_t *)_hdl)->r2; \ |
|||
_r3 = ((smc_ctx_t *)_hdl)->r3; \ |
|||
_r4 = ((smc_ctx_t *)_hdl)->r4; \ |
|||
} |
|||
|
|||
/* ------------------------------------------------------------------------
|
|||
* Helper APIs for setting and retrieving appropriate `smc_ctx_t`. |
|||
* These functions need to implemented by the BL including this library. |
|||
* ------------------------------------------------------------------------ |
|||
*/ |
|||
|
|||
/* Get the pointer to `smc_ctx_t` corresponding to the security state. */ |
|||
void *smc_get_ctx(unsigned int security_state); |
|||
|
|||
/* Set the next `smc_ctx_t` corresponding to the security state. */ |
|||
void smc_set_next_ctx(unsigned int security_state); |
|||
|
|||
/* Get the pointer to next `smc_ctx_t` already set by `smc_set_next_ctx()`. */ |
|||
void *smc_get_next_ctx(void); |
|||
|
|||
#endif /*__ASSEMBLY__*/ |
|||
|
|||
#endif /* __SMCCC_HELPERS_H__ */ |
@ -0,0 +1,199 @@ |
|||
/* |
|||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
#ifndef __SMCCC_MACROS_S__ |
|||
#define __SMCCC_MACROS_S__ |
|||
|
|||
#include <arch.h> |
|||
|
|||
/* |
|||
* Macro to save the General purpose registers (r0 - r12), the banked |
|||
* spsr, lr, sp registers and the `scr` register to the SMC context on entry |
|||
* due a SMC call. The `lr` of the current mode (monitor) is expected to be |
|||
* already saved. The `sp` must point to the `smc_ctx_t` to save to. |
|||
* Additionally, also save the 'pmcr' register as this is updated whilst |
|||
* executing in the secure world. |
|||
*/ |
|||
.macro smccc_save_gp_mode_regs |
|||
/* Save r0 - r12 in the SMC context */ |
|||
stm sp, {r0-r12} |
|||
mov r0, sp |
|||
add r0, r0, #SMC_CTX_SP_USR |
|||
|
|||
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) |
|||
/* Must be in secure state to restore Monitor mode */ |
|||
ldcopr r4, SCR |
|||
bic r2, r4, #SCR_NS_BIT |
|||
stcopr r2, SCR |
|||
isb |
|||
|
|||
cps #MODE32_sys |
|||
stm r0!, {sp, lr} |
|||
|
|||
cps #MODE32_irq |
|||
mrs r2, spsr |
|||
stm r0!, {r2, sp, lr} |
|||
|
|||
cps #MODE32_fiq |
|||
mrs r2, spsr |
|||
stm r0!, {r2, sp, lr} |
|||
|
|||
cps #MODE32_svc |
|||
mrs r2, spsr |
|||
stm r0!, {r2, sp, lr} |
|||
|
|||
cps #MODE32_abt |
|||
mrs r2, spsr |
|||
stm r0!, {r2, sp, lr} |
|||
|
|||
cps #MODE32_und |
|||
mrs r2, spsr |
|||
stm r0!, {r2, sp, lr} |
|||
|
|||
/* lr_mon is already saved by caller */ |
|||
cps #MODE32_mon |
|||
mrs r2, spsr |
|||
stm r0!, {r2} |
|||
|
|||
stcopr r4, SCR |
|||
isb |
|||
#else |
|||
/* Save the banked registers including the current SPSR and LR */ |
|||
mrs r4, sp_usr |
|||
mrs r5, lr_usr |
|||
mrs r6, spsr_irq |
|||
mrs r7, sp_irq |
|||
mrs r8, lr_irq |
|||
mrs r9, spsr_fiq |
|||
mrs r10, sp_fiq |
|||
mrs r11, lr_fiq |
|||
mrs r12, spsr_svc |
|||
stm r0!, {r4-r12} |
|||
|
|||
mrs r4, sp_svc |
|||
mrs r5, lr_svc |
|||
mrs r6, spsr_abt |
|||
mrs r7, sp_abt |
|||
mrs r8, lr_abt |
|||
mrs r9, spsr_und |
|||
mrs r10, sp_und |
|||
mrs r11, lr_und |
|||
mrs r12, spsr |
|||
stm r0!, {r4-r12} |
|||
/* lr_mon is already saved by caller */ |
|||
|
|||
ldcopr r4, SCR |
|||
#endif |
|||
str r4, [sp, #SMC_CTX_SCR] |
|||
ldcopr r4, PMCR |
|||
str r4, [sp, #SMC_CTX_PMCR] |
|||
.endm |
|||
|
|||
/* |
|||
* Macro to restore the `smc_ctx_t`, which includes the General purpose |
|||
* registers and banked mode registers, and exit from the monitor mode. |
|||
* r0 must point to the `smc_ctx_t` to restore from. |
|||
*/ |
|||
.macro monitor_exit |
|||
/* |
|||
* Save the current sp and restore the smc context |
|||
* pointer to sp which will be used for handling the |
|||
* next SMC. |
|||
*/ |
|||
str sp, [r0, #SMC_CTX_SP_MON] |
|||
mov sp, r0 |
|||
|
|||
/* |
|||
* Restore SCR first so that we access the right banked register |
|||
* when the other mode registers are restored. |
|||
*/ |
|||
ldr r1, [r0, #SMC_CTX_SCR] |
|||
stcopr r1, SCR |
|||
isb |
|||
|
|||
/* |
|||
* Restore the PMCR register. |
|||
*/ |
|||
ldr r1, [r0, #SMC_CTX_PMCR] |
|||
stcopr r1, PMCR |
|||
|
|||
/* Restore the banked registers including the current SPSR */ |
|||
add r1, r0, #SMC_CTX_SP_USR |
|||
|
|||
#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) |
|||
/* Must be in secure state to restore Monitor mode */ |
|||
ldcopr r4, SCR |
|||
bic r2, r4, #SCR_NS_BIT |
|||
stcopr r2, SCR |
|||
isb |
|||
|
|||
cps #MODE32_sys |
|||
ldm r1!, {sp, lr} |
|||
|
|||
cps #MODE32_irq |
|||
ldm r1!, {r2, sp, lr} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
cps #MODE32_fiq |
|||
ldm r1!, {r2, sp, lr} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
cps #MODE32_svc |
|||
ldm r1!, {r2, sp, lr} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
cps #MODE32_abt |
|||
ldm r1!, {r2, sp, lr} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
cps #MODE32_und |
|||
ldm r1!, {r2, sp, lr} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
cps #MODE32_mon |
|||
ldm r1!, {r2} |
|||
msr spsr_fsxc, r2 |
|||
|
|||
stcopr r4, SCR |
|||
isb |
|||
#else |
|||
ldm r1!, {r4-r12} |
|||
msr sp_usr, r4 |
|||
msr lr_usr, r5 |
|||
msr spsr_irq, r6 |
|||
msr sp_irq, r7 |
|||
msr lr_irq, r8 |
|||
msr spsr_fiq, r9 |
|||
msr sp_fiq, r10 |
|||
msr lr_fiq, r11 |
|||
msr spsr_svc, r12 |
|||
|
|||
ldm r1!, {r4-r12} |
|||
msr sp_svc, r4 |
|||
msr lr_svc, r5 |
|||
msr spsr_abt, r6 |
|||
msr sp_abt, r7 |
|||
msr lr_abt, r8 |
|||
msr spsr_und, r9 |
|||
msr sp_und, r10 |
|||
msr lr_und, r11 |
|||
/* |
|||
* Use the `_fsxc` suffix explicitly to instruct the assembler |
|||
* to update all the 32 bits of SPSR. Else, by default, the |
|||
* assembler assumes `_fc` suffix which only modifies |
|||
* f->[31:24] and c->[7:0] bits of SPSR. |
|||
*/ |
|||
msr spsr_fsxc, r12 |
|||
#endif |
|||
|
|||
/* Restore the LR */ |
|||
ldr lr, [r0, #SMC_CTX_LR_MON] |
|||
|
|||
/* Restore the rest of the general purpose registers */ |
|||
ldm r0, {r0-r12} |
|||
eret |
|||
.endm |
|||
|
|||
#endif /* __SMCCC_MACROS_S__ */ |
@ -0,0 +1,91 @@ |
|||
/*
|
|||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __SMCCC_HELPERS_H__ |
|||
#define __SMCCC_HELPERS_H__ |
|||
|
|||
#include <smccc.h> |
|||
|
|||
#ifndef __ASSEMBLY__ |
|||
#include <context.h> |
|||
|
|||
/* Convenience macros to return from SMC handler */ |
|||
#define SMC_RET0(_h) { \ |
|||
return (uint64_t) (_h); \ |
|||
} |
|||
#define SMC_RET1(_h, _x0) { \ |
|||
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X0), (_x0)); \ |
|||
SMC_RET0(_h); \ |
|||
} |
|||
#define SMC_RET2(_h, _x0, _x1) { \ |
|||
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X1), (_x1)); \ |
|||
SMC_RET1(_h, (_x0)); \ |
|||
} |
|||
#define SMC_RET3(_h, _x0, _x1, _x2) { \ |
|||
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X2), (_x2)); \ |
|||
SMC_RET2(_h, (_x0), (_x1)); \ |
|||
} |
|||
#define SMC_RET4(_h, _x0, _x1, _x2, _x3) { \ |
|||
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X3), (_x3)); \ |
|||
SMC_RET3(_h, (_x0), (_x1), (_x2)); \ |
|||
} |
|||
#define SMC_RET5(_h, _x0, _x1, _x2, _x3, _x4) { \ |
|||
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X4), (_x4)); \ |
|||
SMC_RET4(_h, (_x0), (_x1), (_x2), (_x3)); \ |
|||
} |
|||
#define SMC_RET6(_h, _x0, _x1, _x2, _x3, _x4, _x5) { \ |
|||
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X5), (_x5)); \ |
|||
SMC_RET5(_h, (_x0), (_x1), (_x2), (_x3), (_x4)); \ |
|||
} |
|||
#define SMC_RET7(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6) { \ |
|||
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X6), (_x6)); \ |
|||
SMC_RET6(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5)); \ |
|||
} |
|||
#define SMC_RET8(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7) { \ |
|||
write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X7), (_x7)); \ |
|||
SMC_RET7(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5), (_x6)); \ |
|||
} |
|||
|
|||
/*
|
|||
* Convenience macros to access general purpose registers using handle provided |
|||
* to SMC handler. These take the offset values defined in context.h |
|||
*/ |
|||
#define SMC_GET_GP(_h, _g) \ |
|||
read_ctx_reg((get_gpregs_ctx(_h)), (_g)) |
|||
#define SMC_SET_GP(_h, _g, _v) \ |
|||
write_ctx_reg((get_gpregs_ctx(_h)), (_g), (_v)) |
|||
|
|||
/*
|
|||
* Convenience macros to access EL3 context registers using handle provided to |
|||
* SMC handler. These take the offset values defined in context.h |
|||
*/ |
|||
#define SMC_GET_EL3(_h, _e) \ |
|||
read_ctx_reg((get_el3state_ctx(_h)), (_e)) |
|||
#define SMC_SET_EL3(_h, _e, _v) \ |
|||
write_ctx_reg((get_el3state_ctx(_h)), (_e), (_v)) |
|||
|
|||
/* Return a UUID in the SMC return registers */ |
|||
#define SMC_UUID_RET(_h, _uuid) \ |
|||
SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \ |
|||
((const uint32_t *) &(_uuid))[1], \ |
|||
((const uint32_t *) &(_uuid))[2], \ |
|||
((const uint32_t *) &(_uuid))[3]) |
|||
|
|||
/*
|
|||
* Helper macro to retrieve the SMC parameters from cpu_context_t. |
|||
*/ |
|||
#define get_smc_params_from_ctx(_hdl, _x1, _x2, _x3, _x4) \ |
|||
do { \ |
|||
const gp_regs_t *regs = get_gpregs_ctx(_hdl); \ |
|||
_x1 = read_ctx_reg(regs, CTX_GPREG_X1); \ |
|||
_x2 = read_ctx_reg(regs, CTX_GPREG_X2); \ |
|||
_x3 = read_ctx_reg(regs, CTX_GPREG_X3); \ |
|||
_x4 = read_ctx_reg(regs, CTX_GPREG_X4); \ |
|||
} while (0) |
|||
|
|||
#endif /*__ASSEMBLY__*/ |
|||
|
|||
#endif /* __SMCCC_HELPERS_H__ */ |
@ -0,0 +1,109 @@ |
|||
/*
|
|||
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef __SMCCC_H__ |
|||
#define __SMCCC_H__ |
|||
|
|||
#include <utils_def.h> |
|||
|
|||
/*******************************************************************************
|
|||
* Bit definitions inside the function id as per the SMC calling convention |
|||
******************************************************************************/ |
|||
#define FUNCID_TYPE_SHIFT U(31) |
|||
#define FUNCID_CC_SHIFT U(30) |
|||
#define FUNCID_OEN_SHIFT U(24) |
|||
#define FUNCID_NUM_SHIFT U(0) |
|||
|
|||
#define FUNCID_TYPE_MASK U(0x1) |
|||
#define FUNCID_CC_MASK U(0x1) |
|||
#define FUNCID_OEN_MASK U(0x3f) |
|||
#define FUNCID_NUM_MASK U(0xffff) |
|||
|
|||
#define FUNCID_TYPE_WIDTH U(1) |
|||
#define FUNCID_CC_WIDTH U(1) |
|||
#define FUNCID_OEN_WIDTH U(6) |
|||
#define FUNCID_NUM_WIDTH U(16) |
|||
|
|||
#define GET_SMC_CC(id) ((id >> FUNCID_CC_SHIFT) & \ |
|||
FUNCID_CC_MASK) |
|||
#define GET_SMC_TYPE(id) ((id >> FUNCID_TYPE_SHIFT) & \ |
|||
FUNCID_TYPE_MASK) |
|||
|
|||
#define SMC_64 U(1) |
|||
#define SMC_32 U(0) |
|||
#define SMC_OK U(0) |
|||
#define SMC_UNK -1 |
|||
#define SMC_TYPE_FAST ULL(1) |
|||
#if !ERROR_DEPRECATED |
|||
#define SMC_TYPE_STD ULL(0) |
|||
#endif |
|||
#define SMC_TYPE_YIELD U(0) |
|||
#define SMC_PREEMPTED -2 |
|||
/*******************************************************************************
|
|||
* 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_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) |
|||
|
|||
#ifndef __ASSEMBLY__ |
|||
|
|||
#include <cassert.h> |
|||
#include <stdint.h> |
|||
|
|||
#define SMCCC_MAJOR_VERSION U(1) |
|||
#define SMCCC_MINOR_VERSION U(1) |
|||
|
|||
#define MAKE_SMCCC_VERSION(_major, _minor) (((_major) << 16) | (_minor)) |
|||
|
|||
/* Various flags passed to SMC handlers */ |
|||
#define SMC_FROM_SECURE (U(0) << 0) |
|||
#define SMC_FROM_NON_SECURE (U(1) << 0) |
|||
|
|||
#define is_caller_non_secure(_f) (!!(_f & SMC_FROM_NON_SECURE)) |
|||
#define is_caller_secure(_f) (!(is_caller_non_secure(_f))) |
|||
|
|||
/* The macro below is used to identify a Standard Service SMC call */ |
|||
#define is_std_svc_call(_fid) ((((_fid) >> FUNCID_OEN_SHIFT) & \ |
|||
FUNCID_OEN_MASK) == OEN_STD_START) |
|||
|
|||
/* The macro below is used to identify a Arm Architectural Service SMC call */ |
|||
#define is_arm_arch_svc_call(_fid) ((((_fid) >> FUNCID_OEN_SHIFT) & \ |
|||
FUNCID_OEN_MASK) == 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) == 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_UUID(_name, _tl, _tm, _th, _cl, _ch, \ |
|||
_n0, _n1, _n2, _n3, _n4, _n5) \ |
|||
CASSERT((uint32_t)(_tl) != (uint32_t) SMC_UNK, invalid_svc_uuid);\ |
|||
static const uuid_t _name = { \ |
|||
_tl, _tm, _th, _cl, _ch, \ |
|||
{ _n0, _n1, _n2, _n3, _n4, _n5 } \ |
|||
} |
|||
|
|||
#endif /*__ASSEMBLY__*/ |
|||
#endif /* __SMCCC_H__ */ |
Loading…
Reference in new issue