blob: 5aeca22397162be3c69b832e65c618b4f1e32934 [file] [log] [blame]
Soby Mathewacc144b2016-05-05 12:53:53 +01001/*
2 * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef __SMCC_HELPERS_H__
32#define __SMCC_HELPERS_H__
33
34#include <smcc.h>
35
36/* These are offsets to registers in smc_ctx_t */
37#define SMC_CTX_GPREG_R0 0x0
38#define SMC_CTX_GPREG_R1 0x4
39#define SMC_CTX_GPREG_R2 0x8
40#define SMC_CTX_GPREG_R3 0xC
41#define SMC_CTX_GPREG_R4 0x10
42#define SMC_CTX_SP_USR 0x34
43#define SMC_CTX_SPSR_MON 0x78
44#define SMC_CTX_LR_MON 0x7C
45#define SMC_CTX_SIZE 0x80
46
47#ifndef __ASSEMBLY__
48#include <cassert.h>
49#include <types.h>
50
51/*
52 * The generic structure to save arguments and callee saved registers during
53 * an SMC. Also this structure is used to store the result return values after
54 * the completion of SMC service.
55 */
56typedef struct smc_ctx {
57 u_register_t r0;
58 u_register_t r1;
59 u_register_t r2;
60 u_register_t r3;
61 u_register_t r4;
62 u_register_t r5;
63 u_register_t r6;
64 u_register_t r7;
65 u_register_t r8;
66 u_register_t r9;
67 u_register_t r10;
68 u_register_t r11;
69 u_register_t r12;
70 /* spsr_usr doesn't exist */
71 u_register_t sp_usr;
72 u_register_t lr_usr;
73 u_register_t spsr_irq;
74 u_register_t sp_irq;
75 u_register_t lr_irq;
76 u_register_t spsr_fiq;
77 u_register_t sp_fiq;
78 u_register_t lr_fiq;
79 u_register_t spsr_svc;
80 u_register_t sp_svc;
81 u_register_t lr_svc;
82 u_register_t spsr_abt;
83 u_register_t sp_abt;
84 u_register_t lr_abt;
85 u_register_t spsr_und;
86 u_register_t sp_und;
87 u_register_t lr_und;
88 u_register_t spsr_mon;
89 /* No need to save 'sp_mon' because we are already in monitor mode */
90 u_register_t lr_mon;
91} smc_ctx_t;
92
93/*
94 * Compile time assertions related to the 'smc_context' structure to
95 * ensure that the assembler and the compiler view of the offsets of
96 * the structure members is the same.
97 */
98CASSERT(SMC_CTX_GPREG_R0 == __builtin_offsetof(smc_ctx_t, r0), \
99 assert_smc_ctx_greg_r0_offset_mismatch);
100CASSERT(SMC_CTX_GPREG_R1 == __builtin_offsetof(smc_ctx_t, r1), \
101 assert_smc_ctx_greg_r1_offset_mismatch);
102CASSERT(SMC_CTX_GPREG_R2 == __builtin_offsetof(smc_ctx_t, r2), \
103 assert_smc_ctx_greg_r2_offset_mismatch);
104CASSERT(SMC_CTX_GPREG_R3 == __builtin_offsetof(smc_ctx_t, r3), \
105 assert_smc_ctx_greg_r3_offset_mismatch);
106CASSERT(SMC_CTX_GPREG_R4 == __builtin_offsetof(smc_ctx_t, r4), \
107 assert_smc_ctx_greg_r4_offset_mismatch);
108CASSERT(SMC_CTX_SP_USR == __builtin_offsetof(smc_ctx_t, sp_usr), \
109 assert_smc_ctx_sp_usr_offset_mismatch);
110CASSERT(SMC_CTX_LR_MON == __builtin_offsetof(smc_ctx_t, lr_mon), \
111 assert_smc_ctx_lr_mon_offset_mismatch);
112CASSERT(SMC_CTX_SPSR_MON == __builtin_offsetof(smc_ctx_t, spsr_mon), \
113 assert_smc_ctx_spsr_mon_offset_mismatch);
114
115CASSERT(SMC_CTX_SIZE == sizeof(smc_ctx_t), assert_smc_ctx_size_mismatch);
116
117/* Convenience macros to return from SMC handler */
118#define SMC_RET0(_h) { \
119 return (uintptr_t)(_h); \
120}
121#define SMC_RET1(_h, _r0) { \
122 ((smc_ctx_t *)(_h))->r0 = (_r0); \
123 SMC_RET0(_h); \
124}
125#define SMC_RET2(_h, _r0, _r1) { \
126 ((smc_ctx_t *)(_h))->r1 = (_r1); \
127 SMC_RET1(_h, (_r0)); \
128}
129#define SMC_RET3(_h, _r0, _r1, _r2) { \
130 ((smc_ctx_t *)(_h))->r2 = (_r2); \
131 SMC_RET2(_h, (_r0), (_r1)); \
132}
133#define SMC_RET4(_h, _r0, _r1, _r2, _r3) { \
134 ((smc_ctx_t *)(_h))->r3 = (_r3); \
135 SMC_RET3(_h, (_r0), (_r1), (_r2)); \
136}
137
138/* Return a UUID in the SMC return registers */
139#define SMC_UUID_RET(_h, _uuid) \
140 SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \
141 ((const uint32_t *) &(_uuid))[1], \
142 ((const uint32_t *) &(_uuid))[2], \
143 ((const uint32_t *) &(_uuid))[3])
144
145/*
146 * Helper macro to retrieve the SMC parameters from smc_ctx_t.
147 */
148#define get_smc_params_from_ctx(_hdl, _r1, _r2, _r3, _r4) { \
149 _r1 = ((smc_ctx_t *)_hdl)->r1; \
150 _r2 = ((smc_ctx_t *)_hdl)->r2; \
151 _r3 = ((smc_ctx_t *)_hdl)->r3; \
152 _r4 = ((smc_ctx_t *)_hdl)->r4; \
153 }
154
155/* ------------------------------------------------------------------------
156 * Helper APIs for setting and retrieving appropriate `smc_ctx_t`.
157 * These functions need to implemented by the BL including this library.
158 * ------------------------------------------------------------------------
159 */
160
161/* Get the pointer to `smc_ctx_t` corresponding to the security state. */
162void *smc_get_ctx(int security_state);
163
164/* Set the next `smc_ctx_t` corresponding to the security state. */
165void smc_set_next_ctx(int security_state);
166
167/* Get the pointer to next `smc_ctx_t` already set by `smc_set_next_ctx()`. */
168void *smc_get_next_ctx(void);
169
170#endif /*__ASSEMBLY__*/
171#endif /* __SMCC_HELPERS_H__ */