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