1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #ifndef SMC_H
7 #define SMC_H
8 
9 #include <utils_def.h>
10 
11 /* FID: Type - Fast Call */
12 #define SMC_TYPE_SHIFT		U(31)
13 #define SMC_TYPE_MASK		U(1)
14 #define SMC_TYPE_FAST		U(1)
15 
16 /* FID: Calling convention - SMC32/SMC64 */
17 #define SMC_CC_SHIFT		U(30)
18 #define SMC_CC_MASK		U(1)
19 #define SMC_CC_SMC32		U(0)
20 #define SMC_CC_SMC64		U(1)
21 
22 /* FID: Owning entity number - Standard Secure Service Calls */
23 #define SMC_OEN_SHIFT		U(24)
24 #define SMC_OEN_MASK		U(0x3F)
25 #define SMC_OEN_STD		U(0x4)
26 #define SMC_OEN_ARCH		U(0x0)
27 
28 /* FID: Must be zero (MBZ) */
29 #define SMC_MBZ_SHIFT		U(16)
30 #define SMC_MBZ_MASK		U(0xFF)
31 #define SMC_MBZ_ZERO		U(0x0)
32 
33 /* FID: Function number */
34 #define SMC_FNUM_SHIFT		U(0)
35 #define SMC_FNUM_MASK		U(0xFFFF)
36 
37 #define SMC_FIELD_VAL(_field, _val)					    \
38 	(((_val) & SMC_##_field##_MASK) << SMC_##_field##_SHIFT)
39 
40 #define SMC_SET_FIELD(_init_val, _field, _val)                              \
41 	(((_init_val) & ~SMC_FIELD_VAL(_field, SMC_##_field##_MASK)) |	    \
42 	 SMC_FIELD_VAL(_field, _val))
43 
44 #define SMC_GET_FIELD(_fid, _field)					    \
45 	(((_fid) >> SMC_##_field##_SHIFT) & SMC_##_field##_MASK)
46 
47 /* Arm Architecture Call range function IDs */
48 				/* 0x80000000 */
49 #define SMC_ARCH_CALL_BASE	(SMC_SET_FIELD(U(0), TYPE, SMC_TYPE_FAST) | \
50 				SMC_SET_FIELD(U(0), OEN, SMC_OEN_ARCH))
51 
52 				/* 0x8000FFFF */
53 #define SMC_ARCH_CALL_LIMIT	(SMC_SET_FIELD(SMC_ARCH_CALL_BASE, FNUM,    \
54 					       U(0xFFFF)))
55 
56 /*
57  * We allocate all RMM calls as function IDs within the Standard Secure
58  * Service Call range category defined in the SMCCC.
59  */
60 				/* 0x84000000 */
61 #define SMC_STD_CALL_BASE	(SMC_SET_FIELD(U(0), TYPE, SMC_TYPE_FAST) | \
62 				SMC_SET_FIELD(U(0), OEN, SMC_OEN_STD))
63 
64 				/* 0x840001CF */
65 #define SMC_STD_CALL_LIMIT	(SMC_SET_FIELD(SMC_STD_CALL_BASE, FNUM,     \
66 					       U(0x1CF)))
67 
68 /* STD calls FNUM Min/Max ranges */
69 #define SMC32_PSCI_FNUM_MIN	(U(0x0))
70 #define SMC32_PSCI_FNUM_MAX	(U(0x14))
71 
72 #define SMC64_PSCI_FNUM_MIN	(U(0x0))
73 #define SMC64_PSCI_FNUM_MAX	(U(0x14))
74 
75 #define SMC64_RMI_FNUM_MIN	(U(0x150))
76 #define SMC64_RMI_FNUM_MAX	(U(0x169))
77 
78 #define SMC64_RSI_FNUM_MIN	(U(0x190))
79 #define SMC64_RSI_FNUM_MAX	(U(0x1AF))
80 
81 #define SMC64_RMM_EL3_FNUM_MIN	(U(0x1B0))
82 #define SMC64_RMM_EL3_FNUM_MAX	(U(0x1CF))
83 
84 /* Utility macros for FID range values */
85 #define SMC32_ARCH_FID(_offset)						   \
86 	(SMC_SET_FIELD(SMC_ARCH_CALL_BASE, CC, SMC_CC_SMC32)		|  \
87 	 SMC_SET_FIELD(SMC_ARCH_CALL_BASE, FNUM, (_offset)))
88 
89 #define SMC32_STD_FID(_range, _offset)					   \
90 	(SMC_SET_FIELD(SMC_STD_CALL_BASE, CC, SMC_CC_SMC32)		|  \
91 	 SMC_SET_FIELD(SMC_STD_CALL_BASE, FNUM,				   \
92 	 (SMC32_##_range##_FNUM_MIN + (_offset))))
93 
94 #define SMC64_STD_FID(_range, _offset)					   \
95 	(SMC_SET_FIELD(SMC_STD_CALL_BASE, CC, SMC_CC_SMC64)		|  \
96 	 SMC_SET_FIELD(SMC_STD_CALL_BASE, FNUM,				   \
97 	 (SMC64_##_range##_FNUM_MIN + (_offset))))
98 
99 #define IS_SMC64_FID_IN_RANGE(_range, _fid)				   \
100 	((SMC_GET_FIELD(_fid, FNUM)	>= SMC64_##_range##_FNUM_MIN)	&& \
101 	 (SMC_GET_FIELD(_fid, FNUM)	<= SMC64_##_range##_FNUM_MAX))
102 
103 #define IS_SMC32_FID_IN_RANGE(_range, _fid)				   \
104 	((SMC_GET_FIELD(_fid, FNUM)	>= SMC32_##_range##_FNUM_MIN)	&& \
105 	 (SMC_GET_FIELD(_fid, FNUM)	<= SMC32_##_range##_FNUM_MAX))
106 
107 #define IS_SMC64_FID_STD_FAST(_fid)					   \
108 	(((_fid) & ~SMC_FIELD_VAL(FNUM, SMC_FNUM_MASK)) ==		   \
109 	 ((SMC_FIELD_VAL(CC, SMC_CC_SMC64)				|  \
110 	   SMC_FIELD_VAL(TYPE, SMC_TYPE_FAST)				|  \
111 	   SMC_FIELD_VAL(OEN, SMC_OEN_STD))))
112 
113 #define IS_SMC32_FID_STD_FAST(_fid)					   \
114 	(((_fid) & ~SMC_FIELD_VAL(FNUM, SMC_FNUM_MASK)) ==		   \
115 	 ((SMC_FIELD_VAL(CC, SMC_CC_SMC32)				|  \
116 	   SMC_FIELD_VAL(TYPE, SMC_TYPE_FAST)				|  \
117 	   SMC_FIELD_VAL(OEN, SMC_OEN_STD))))
118 
119 #define IS_SMC64_STD_FAST_IN_RANGE(_range, _fid)			   \
120 	(IS_SMC64_FID_STD_FAST(_fid) && IS_SMC64_FID_IN_RANGE(_range, _fid))
121 
122 #define IS_SMC32_STD_FAST_IN_RANGE(_range, _fid)			   \
123 	(IS_SMC32_FID_STD_FAST(_fid) && IS_SMC32_FID_IN_RANGE(_range, _fid))
124 
125 #define SMC64_NUM_FIDS_IN_RANGE(_range)					   \
126 	(SMC64_##_range##_FNUM_MAX - SMC64_##_range##_FNUM_MIN + 1)
127 
128 /* Gets the offset in a range. Inputs must be pre-verified */
129 #define SMC64_FID_OFFSET_FROM_RANGE_MIN(_range, _fid)			   \
130 	(SMC_GET_FIELD(_fid, FNUM) - SMC64_##_range##_FNUM_MIN)
131 
132 /* Implementation defined FID values */
133 					/* 0x18F */
134 #define SMC_RMM_REQ_COMPLETE		SMC64_STD_FID(RMI, U(0x3F))
135 
136 					/* 0x1B0 - 0x1B3 */
137 #define SMC_ASC_MARK_SECURE		SMC64_STD_FID(RMM_EL3, U(0))
138 #define SMC_ASC_MARK_NONSECURE		SMC64_STD_FID(RMM_EL3, U(1))
139 
140 /* ARM ARCH call FIDs */
141 #define SMCCC_VERSION			SMC32_ARCH_FID(U(0))
142 #define SMCCC_ARCH_FEATURES		SMC32_ARCH_FID(U(1))
143 #define SMCCC_ARCH_SOC_ID		SMC32_ARCH_FID(U(2))
144 #define SMCCC_ARCH_WORKAROUND_2		SMC32_ARCH_FID(U(0x7FFF))
145 #define SMCCC_ARCH_WORKAROUND_1		SMC32_ARCH_FID(U(0x8000))
146 
147 /* Implemented version of the SMC Calling Convention */
148 #define SMCCC_VERSION_MAJOR	U(1)
149 #define SMCCC_VERSION_MINOR	U(2)
150 
151 /*
152  * SMCCC version encoding:
153  *  Bit[31] must be zero
154  *  Bits [30:16] Major version
155  *  Bits [15:0] Minor version
156  */
157 #define SMCCC_VERSION_NUMBER						  \
158 	((SMCCC_VERSION_MAJOR << U(16)) | SMCCC_VERSION_MINOR)
159 
160 /* SMCCC return codes */
161 #define SMC_SUCCESS		0
162 #define SMC_NOT_SUPPORTED	(-1)
163 #define SMC_NOT_REQUIRED	(-2)
164 #define SMC_INVALID_PARAMETER	(-3)
165 
166 #define SMC_UNKNOWN		(-1)
167 
168 #ifndef __ASSEMBLER__
169 unsigned long monitor_call(unsigned long id,
170 			unsigned long arg0,
171 			unsigned long arg1,
172 			unsigned long arg2,
173 			unsigned long arg3,
174 			unsigned long arg4,
175 			unsigned long arg5);
176 
177 /* Result registers X0-X4 */
178 #define SMC_RESULT_REGS		5U
179 
180 struct smc_result {
181 	unsigned long x[SMC_RESULT_REGS];
182 };
183 
184 void monitor_call_with_res(unsigned long id,
185 			   unsigned long arg0,
186 			   unsigned long arg1,
187 			   unsigned long arg2,
188 			   unsigned long arg3,
189 			   unsigned long arg4,
190 			   unsigned long arg5,
191 			   struct smc_result *res);
192 
193 #endif /* __ASSEMBLER__ */
194 
195 #endif /* SMC_H */
196