1*f5478dedSAntonio Nino Diaz /* 2*f5478dedSAntonio Nino Diaz * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. 3*f5478dedSAntonio Nino Diaz * 4*f5478dedSAntonio Nino Diaz * SPDX-License-Identifier: BSD-3-Clause 5*f5478dedSAntonio Nino Diaz */ 6*f5478dedSAntonio Nino Diaz 7*f5478dedSAntonio Nino Diaz #ifndef SMCCC_HELPERS_H 8*f5478dedSAntonio Nino Diaz #define SMCCC_HELPERS_H 9*f5478dedSAntonio Nino Diaz 10*f5478dedSAntonio Nino Diaz #include <smccc.h> 11*f5478dedSAntonio Nino Diaz 12*f5478dedSAntonio Nino Diaz /* These are offsets to registers in smc_ctx_t */ 13*f5478dedSAntonio Nino Diaz #define SMC_CTX_GPREG_R0 U(0x0) 14*f5478dedSAntonio Nino Diaz #define SMC_CTX_GPREG_R1 U(0x4) 15*f5478dedSAntonio Nino Diaz #define SMC_CTX_GPREG_R2 U(0x8) 16*f5478dedSAntonio Nino Diaz #define SMC_CTX_GPREG_R3 U(0xC) 17*f5478dedSAntonio Nino Diaz #define SMC_CTX_GPREG_R4 U(0x10) 18*f5478dedSAntonio Nino Diaz #define SMC_CTX_GPREG_R5 U(0x14) 19*f5478dedSAntonio Nino Diaz #define SMC_CTX_SP_USR U(0x34) 20*f5478dedSAntonio Nino Diaz #define SMC_CTX_SPSR_MON U(0x78) 21*f5478dedSAntonio Nino Diaz #define SMC_CTX_SP_MON U(0x7C) 22*f5478dedSAntonio Nino Diaz #define SMC_CTX_LR_MON U(0x80) 23*f5478dedSAntonio Nino Diaz #define SMC_CTX_SCR U(0x84) 24*f5478dedSAntonio Nino Diaz #define SMC_CTX_PMCR U(0x88) 25*f5478dedSAntonio Nino Diaz #define SMC_CTX_SIZE U(0x90) 26*f5478dedSAntonio Nino Diaz 27*f5478dedSAntonio Nino Diaz #ifndef __ASSEMBLY__ 28*f5478dedSAntonio Nino Diaz #include <cassert.h> 29*f5478dedSAntonio Nino Diaz #include <stdint.h> 30*f5478dedSAntonio Nino Diaz 31*f5478dedSAntonio Nino Diaz /* 32*f5478dedSAntonio Nino Diaz * The generic structure to save arguments and callee saved registers during 33*f5478dedSAntonio Nino Diaz * an SMC. Also this structure is used to store the result return values after 34*f5478dedSAntonio Nino Diaz * the completion of SMC service. 35*f5478dedSAntonio Nino Diaz */ 36*f5478dedSAntonio Nino Diaz typedef struct smc_ctx { 37*f5478dedSAntonio Nino Diaz u_register_t r0; 38*f5478dedSAntonio Nino Diaz u_register_t r1; 39*f5478dedSAntonio Nino Diaz u_register_t r2; 40*f5478dedSAntonio Nino Diaz u_register_t r3; 41*f5478dedSAntonio Nino Diaz u_register_t r4; 42*f5478dedSAntonio Nino Diaz u_register_t r5; 43*f5478dedSAntonio Nino Diaz u_register_t r6; 44*f5478dedSAntonio Nino Diaz u_register_t r7; 45*f5478dedSAntonio Nino Diaz u_register_t r8; 46*f5478dedSAntonio Nino Diaz u_register_t r9; 47*f5478dedSAntonio Nino Diaz u_register_t r10; 48*f5478dedSAntonio Nino Diaz u_register_t r11; 49*f5478dedSAntonio Nino Diaz u_register_t r12; 50*f5478dedSAntonio Nino Diaz /* spsr_usr doesn't exist */ 51*f5478dedSAntonio Nino Diaz u_register_t sp_usr; 52*f5478dedSAntonio Nino Diaz u_register_t lr_usr; 53*f5478dedSAntonio Nino Diaz u_register_t spsr_irq; 54*f5478dedSAntonio Nino Diaz u_register_t sp_irq; 55*f5478dedSAntonio Nino Diaz u_register_t lr_irq; 56*f5478dedSAntonio Nino Diaz u_register_t spsr_fiq; 57*f5478dedSAntonio Nino Diaz u_register_t sp_fiq; 58*f5478dedSAntonio Nino Diaz u_register_t lr_fiq; 59*f5478dedSAntonio Nino Diaz u_register_t spsr_svc; 60*f5478dedSAntonio Nino Diaz u_register_t sp_svc; 61*f5478dedSAntonio Nino Diaz u_register_t lr_svc; 62*f5478dedSAntonio Nino Diaz u_register_t spsr_abt; 63*f5478dedSAntonio Nino Diaz u_register_t sp_abt; 64*f5478dedSAntonio Nino Diaz u_register_t lr_abt; 65*f5478dedSAntonio Nino Diaz u_register_t spsr_und; 66*f5478dedSAntonio Nino Diaz u_register_t sp_und; 67*f5478dedSAntonio Nino Diaz u_register_t lr_und; 68*f5478dedSAntonio Nino Diaz u_register_t spsr_mon; 69*f5478dedSAntonio Nino Diaz /* 70*f5478dedSAntonio Nino Diaz * `sp_mon` will point to the C runtime stack in monitor mode. But prior 71*f5478dedSAntonio Nino Diaz * to exit from SMC, this will point to the `smc_ctx_t` so that 72*f5478dedSAntonio Nino Diaz * on next entry due to SMC, the `smc_ctx_t` can be easily accessed. 73*f5478dedSAntonio Nino Diaz */ 74*f5478dedSAntonio Nino Diaz u_register_t sp_mon; 75*f5478dedSAntonio Nino Diaz u_register_t lr_mon; 76*f5478dedSAntonio Nino Diaz u_register_t scr; 77*f5478dedSAntonio Nino Diaz u_register_t pmcr; 78*f5478dedSAntonio Nino Diaz /* 79*f5478dedSAntonio Nino Diaz * The workaround for CVE-2017-5715 requires storing information in 80*f5478dedSAntonio Nino Diaz * the bottom 3 bits of the stack pointer. Add a padding field to 81*f5478dedSAntonio Nino Diaz * force the size of the struct to be a multiple of 8. 82*f5478dedSAntonio Nino Diaz */ 83*f5478dedSAntonio Nino Diaz u_register_t pad; 84*f5478dedSAntonio Nino Diaz } smc_ctx_t __aligned(8); 85*f5478dedSAntonio Nino Diaz 86*f5478dedSAntonio Nino Diaz /* 87*f5478dedSAntonio Nino Diaz * Compile time assertions related to the 'smc_context' structure to 88*f5478dedSAntonio Nino Diaz * ensure that the assembler and the compiler view of the offsets of 89*f5478dedSAntonio Nino Diaz * the structure members is the same. 90*f5478dedSAntonio Nino Diaz */ 91*f5478dedSAntonio Nino Diaz CASSERT(SMC_CTX_GPREG_R0 == __builtin_offsetof(smc_ctx_t, r0), \ 92*f5478dedSAntonio Nino Diaz assert_smc_ctx_greg_r0_offset_mismatch); 93*f5478dedSAntonio Nino Diaz CASSERT(SMC_CTX_GPREG_R1 == __builtin_offsetof(smc_ctx_t, r1), \ 94*f5478dedSAntonio Nino Diaz assert_smc_ctx_greg_r1_offset_mismatch); 95*f5478dedSAntonio Nino Diaz CASSERT(SMC_CTX_GPREG_R2 == __builtin_offsetof(smc_ctx_t, r2), \ 96*f5478dedSAntonio Nino Diaz assert_smc_ctx_greg_r2_offset_mismatch); 97*f5478dedSAntonio Nino Diaz CASSERT(SMC_CTX_GPREG_R3 == __builtin_offsetof(smc_ctx_t, r3), \ 98*f5478dedSAntonio Nino Diaz assert_smc_ctx_greg_r3_offset_mismatch); 99*f5478dedSAntonio Nino Diaz CASSERT(SMC_CTX_GPREG_R4 == __builtin_offsetof(smc_ctx_t, r4), \ 100*f5478dedSAntonio Nino Diaz assert_smc_ctx_greg_r4_offset_mismatch); 101*f5478dedSAntonio Nino Diaz CASSERT(SMC_CTX_SP_USR == __builtin_offsetof(smc_ctx_t, sp_usr), \ 102*f5478dedSAntonio Nino Diaz assert_smc_ctx_sp_usr_offset_mismatch); 103*f5478dedSAntonio Nino Diaz CASSERT(SMC_CTX_LR_MON == __builtin_offsetof(smc_ctx_t, lr_mon), \ 104*f5478dedSAntonio Nino Diaz assert_smc_ctx_lr_mon_offset_mismatch); 105*f5478dedSAntonio Nino Diaz CASSERT(SMC_CTX_SPSR_MON == __builtin_offsetof(smc_ctx_t, spsr_mon), \ 106*f5478dedSAntonio Nino Diaz assert_smc_ctx_spsr_mon_offset_mismatch); 107*f5478dedSAntonio Nino Diaz 108*f5478dedSAntonio Nino Diaz CASSERT((sizeof(smc_ctx_t) & 0x7U) == 0U, assert_smc_ctx_not_aligned); 109*f5478dedSAntonio Nino Diaz CASSERT(SMC_CTX_SIZE == sizeof(smc_ctx_t), assert_smc_ctx_size_mismatch); 110*f5478dedSAntonio Nino Diaz 111*f5478dedSAntonio Nino Diaz /* Convenience macros to return from SMC handler */ 112*f5478dedSAntonio Nino Diaz #define SMC_RET0(_h) { \ 113*f5478dedSAntonio Nino Diaz return (uintptr_t)(_h); \ 114*f5478dedSAntonio Nino Diaz } 115*f5478dedSAntonio Nino Diaz #define SMC_RET1(_h, _r0) { \ 116*f5478dedSAntonio Nino Diaz ((smc_ctx_t *)(_h))->r0 = (_r0); \ 117*f5478dedSAntonio Nino Diaz SMC_RET0(_h); \ 118*f5478dedSAntonio Nino Diaz } 119*f5478dedSAntonio Nino Diaz #define SMC_RET2(_h, _r0, _r1) { \ 120*f5478dedSAntonio Nino Diaz ((smc_ctx_t *)(_h))->r1 = (_r1); \ 121*f5478dedSAntonio Nino Diaz SMC_RET1(_h, (_r0)); \ 122*f5478dedSAntonio Nino Diaz } 123*f5478dedSAntonio Nino Diaz #define SMC_RET3(_h, _r0, _r1, _r2) { \ 124*f5478dedSAntonio Nino Diaz ((smc_ctx_t *)(_h))->r2 = (_r2); \ 125*f5478dedSAntonio Nino Diaz SMC_RET2(_h, (_r0), (_r1)); \ 126*f5478dedSAntonio Nino Diaz } 127*f5478dedSAntonio Nino Diaz #define SMC_RET4(_h, _r0, _r1, _r2, _r3) { \ 128*f5478dedSAntonio Nino Diaz ((smc_ctx_t *)(_h))->r3 = (_r3); \ 129*f5478dedSAntonio Nino Diaz SMC_RET3(_h, (_r0), (_r1), (_r2)); \ 130*f5478dedSAntonio Nino Diaz } 131*f5478dedSAntonio Nino Diaz 132*f5478dedSAntonio Nino Diaz /* 133*f5478dedSAntonio Nino Diaz * Helper macro to retrieve the SMC parameters from smc_ctx_t. 134*f5478dedSAntonio Nino Diaz */ 135*f5478dedSAntonio Nino Diaz #define get_smc_params_from_ctx(_hdl, _r1, _r2, _r3, _r4) { \ 136*f5478dedSAntonio Nino Diaz _r1 = ((smc_ctx_t *)_hdl)->r1; \ 137*f5478dedSAntonio Nino Diaz _r2 = ((smc_ctx_t *)_hdl)->r2; \ 138*f5478dedSAntonio Nino Diaz _r3 = ((smc_ctx_t *)_hdl)->r3; \ 139*f5478dedSAntonio Nino Diaz _r4 = ((smc_ctx_t *)_hdl)->r4; \ 140*f5478dedSAntonio Nino Diaz } 141*f5478dedSAntonio Nino Diaz 142*f5478dedSAntonio Nino Diaz /* ------------------------------------------------------------------------ 143*f5478dedSAntonio Nino Diaz * Helper APIs for setting and retrieving appropriate `smc_ctx_t`. 144*f5478dedSAntonio Nino Diaz * These functions need to implemented by the BL including this library. 145*f5478dedSAntonio Nino Diaz * ------------------------------------------------------------------------ 146*f5478dedSAntonio Nino Diaz */ 147*f5478dedSAntonio Nino Diaz 148*f5478dedSAntonio Nino Diaz /* Get the pointer to `smc_ctx_t` corresponding to the security state. */ 149*f5478dedSAntonio Nino Diaz void *smc_get_ctx(unsigned int security_state); 150*f5478dedSAntonio Nino Diaz 151*f5478dedSAntonio Nino Diaz /* Set the next `smc_ctx_t` corresponding to the security state. */ 152*f5478dedSAntonio Nino Diaz void smc_set_next_ctx(unsigned int security_state); 153*f5478dedSAntonio Nino Diaz 154*f5478dedSAntonio Nino Diaz /* Get the pointer to next `smc_ctx_t` already set by `smc_set_next_ctx()`. */ 155*f5478dedSAntonio Nino Diaz void *smc_get_next_ctx(void); 156*f5478dedSAntonio Nino Diaz 157*f5478dedSAntonio Nino Diaz #endif /*__ASSEMBLY__*/ 158*f5478dedSAntonio Nino Diaz 159*f5478dedSAntonio Nino Diaz #endif /* SMCCC_HELPERS_H */ 160