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