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