blob: bb98f703f068ffff44568451d1e0873fa505a2b0 [file] [log] [blame]
Soby Mathewb4c6df42022-11-09 11:13:29 +00001/*
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
Arunachalam Ganapathyebfab6a2023-08-24 14:44:23 +010033/*
34 * SVE Hint bit (SMCCCv1.3), denoting the absence of SVE specific live state.
35 *
36 * MISRA treats 1U as as 8-bit type variables. So use 1UL and typecast the value
37 * to 'unsigned int'
38 */
AlexeiFedorov1ba649f2023-10-19 13:56:02 +010039#define SMC_SVE_HINT (U(1) << 16)
Arunachalam Ganapathy937b5492023-02-28 11:17:52 +000040
Soby Mathewb4c6df42022-11-09 11:13:29 +000041/* FID: Function number */
42#define SMC_FNUM_SHIFT U(0)
43#define SMC_FNUM_MASK U(0xFFFF)
44
45#define SMC_FIELD_VAL(_field, _val) \
46 (((_val) & SMC_##_field##_MASK) << SMC_##_field##_SHIFT)
47
48#define SMC_SET_FIELD(_init_val, _field, _val) \
49 (((_init_val) & ~SMC_FIELD_VAL(_field, SMC_##_field##_MASK)) | \
50 SMC_FIELD_VAL(_field, _val))
51
52#define SMC_GET_FIELD(_fid, _field) \
53 (((_fid) >> SMC_##_field##_SHIFT) & SMC_##_field##_MASK)
54
55/* Arm Architecture Call range function IDs */
56 /* 0x80000000 */
57#define SMC_ARCH_CALL_BASE (SMC_SET_FIELD(U(0), TYPE, SMC_TYPE_FAST) | \
58 SMC_SET_FIELD(U(0), OEN, SMC_OEN_ARCH))
59
60 /* 0x8000FFFF */
61#define SMC_ARCH_CALL_LIMIT (SMC_SET_FIELD(SMC_ARCH_CALL_BASE, FNUM, \
62 U(0xFFFF)))
63
64/*
65 * We allocate all RMM calls as function IDs within the Standard Secure
66 * Service Call range category defined in the SMCCC.
67 */
68 /* 0x84000000 */
69#define SMC_STD_CALL_BASE (SMC_SET_FIELD(U(0), TYPE, SMC_TYPE_FAST) | \
70 SMC_SET_FIELD(U(0), OEN, SMC_OEN_STD))
71
72 /* 0x840001CF */
73#define SMC_STD_CALL_LIMIT (SMC_SET_FIELD(SMC_STD_CALL_BASE, FNUM, \
74 U(0x1CF)))
75
76/* STD calls FNUM Min/Max ranges */
77#define SMC32_PSCI_FNUM_MIN (U(0x0))
78#define SMC32_PSCI_FNUM_MAX (U(0x14))
79
80#define SMC64_PSCI_FNUM_MIN (U(0x0))
81#define SMC64_PSCI_FNUM_MAX (U(0x14))
82
83#define SMC64_RMI_FNUM_MIN (U(0x150))
84#define SMC64_RMI_FNUM_MAX (U(0x169))
85
86#define SMC64_RSI_FNUM_MIN (U(0x190))
87#define SMC64_RSI_FNUM_MAX (U(0x1AF))
88
89#define SMC64_RMM_EL3_FNUM_MIN (U(0x1B0))
90#define SMC64_RMM_EL3_FNUM_MAX (U(0x1CF))
91
92/* Utility macros for FID range values */
93#define SMC32_ARCH_FID(_offset) \
94 (SMC_SET_FIELD(SMC_ARCH_CALL_BASE, CC, SMC_CC_SMC32) | \
95 SMC_SET_FIELD(SMC_ARCH_CALL_BASE, FNUM, (_offset)))
96
97#define SMC32_STD_FID(_range, _offset) \
98 (SMC_SET_FIELD(SMC_STD_CALL_BASE, CC, SMC_CC_SMC32) | \
99 SMC_SET_FIELD(SMC_STD_CALL_BASE, FNUM, \
100 (SMC32_##_range##_FNUM_MIN + (_offset))))
101
102#define SMC64_STD_FID(_range, _offset) \
103 (SMC_SET_FIELD(SMC_STD_CALL_BASE, CC, SMC_CC_SMC64) | \
104 SMC_SET_FIELD(SMC_STD_CALL_BASE, FNUM, \
105 (SMC64_##_range##_FNUM_MIN + (_offset))))
106
107#define IS_SMC64_FID_IN_RANGE(_range, _fid) \
108 ((SMC_GET_FIELD(_fid, FNUM) >= SMC64_##_range##_FNUM_MIN) && \
109 (SMC_GET_FIELD(_fid, FNUM) <= SMC64_##_range##_FNUM_MAX))
110
111#define IS_SMC32_FID_IN_RANGE(_range, _fid) \
112 ((SMC_GET_FIELD(_fid, FNUM) >= SMC32_##_range##_FNUM_MIN) && \
113 (SMC_GET_FIELD(_fid, FNUM) <= SMC32_##_range##_FNUM_MAX))
114
115#define IS_SMC64_FID_STD_FAST(_fid) \
116 (((_fid) & ~SMC_FIELD_VAL(FNUM, SMC_FNUM_MASK)) == \
117 ((SMC_FIELD_VAL(CC, SMC_CC_SMC64) | \
118 SMC_FIELD_VAL(TYPE, SMC_TYPE_FAST) | \
119 SMC_FIELD_VAL(OEN, SMC_OEN_STD))))
120
121#define IS_SMC32_FID_STD_FAST(_fid) \
122 (((_fid) & ~SMC_FIELD_VAL(FNUM, SMC_FNUM_MASK)) == \
123 ((SMC_FIELD_VAL(CC, SMC_CC_SMC32) | \
124 SMC_FIELD_VAL(TYPE, SMC_TYPE_FAST) | \
125 SMC_FIELD_VAL(OEN, SMC_OEN_STD))))
126
127#define IS_SMC64_STD_FAST_IN_RANGE(_range, _fid) \
128 (IS_SMC64_FID_STD_FAST(_fid) && IS_SMC64_FID_IN_RANGE(_range, _fid))
129
130#define IS_SMC32_STD_FAST_IN_RANGE(_range, _fid) \
131 (IS_SMC32_FID_STD_FAST(_fid) && IS_SMC32_FID_IN_RANGE(_range, _fid))
132
133#define SMC64_NUM_FIDS_IN_RANGE(_range) \
Shruti Gupta0e378132023-12-05 10:06:46 +0000134 (SMC64_##_range##_FNUM_MAX - SMC64_##_range##_FNUM_MIN + 1U)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000135
136/* Gets the offset in a range. Inputs must be pre-verified */
137#define SMC64_FID_OFFSET_FROM_RANGE_MIN(_range, _fid) \
138 (SMC_GET_FIELD(_fid, FNUM) - SMC64_##_range##_FNUM_MIN)
139
140/* Implementation defined FID values */
141 /* 0x18F */
142#define SMC_RMM_REQ_COMPLETE SMC64_STD_FID(RMI, U(0x3F))
143
Soby Mathewb4c6df42022-11-09 11:13:29 +0000144/* ARM ARCH call FIDs */
145#define SMCCC_VERSION SMC32_ARCH_FID(U(0))
146#define SMCCC_ARCH_FEATURES SMC32_ARCH_FID(U(1))
147#define SMCCC_ARCH_SOC_ID SMC32_ARCH_FID(U(2))
148#define SMCCC_ARCH_WORKAROUND_2 SMC32_ARCH_FID(U(0x7FFF))
149#define SMCCC_ARCH_WORKAROUND_1 SMC32_ARCH_FID(U(0x8000))
150
151/* Implemented version of the SMC Calling Convention */
152#define SMCCC_VERSION_MAJOR U(1)
153#define SMCCC_VERSION_MINOR U(2)
154
155/*
156 * SMCCC version encoding:
157 * Bit[31] must be zero
158 * Bits [30:16] Major version
159 * Bits [15:0] Minor version
160 */
161#define SMCCC_VERSION_NUMBER \
162 ((SMCCC_VERSION_MAJOR << U(16)) | SMCCC_VERSION_MINOR)
163
164/* SMCCC return codes */
AlexeiFedorov120d7d02023-08-02 16:51:48 +0100165#define SMC_SUCCESS (unsigned long)(0)
166#define SMC_NOT_SUPPORTED (unsigned long)(-1)
167#define SMC_NOT_REQUIRED (unsigned long)(-2)
168#define SMC_INVALID_PARAMETER (unsigned long)(-3)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000169
AlexeiFedorov120d7d02023-08-02 16:51:48 +0100170#define SMC_UNKNOWN (unsigned long)(-1)
Soby Mathewb4c6df42022-11-09 11:13:29 +0000171
172#ifndef __ASSEMBLER__
173unsigned long monitor_call(unsigned long id,
174 unsigned long arg0,
175 unsigned long arg1,
176 unsigned long arg2,
177 unsigned long arg3,
178 unsigned long arg4,
179 unsigned long arg5);
180
181/* Result registers X0-X4 */
182#define SMC_RESULT_REGS 5U
183
184struct smc_result {
185 unsigned long x[SMC_RESULT_REGS];
186};
187
188void monitor_call_with_res(unsigned long id,
189 unsigned long arg0,
190 unsigned long arg1,
191 unsigned long arg2,
192 unsigned long arg3,
193 unsigned long arg4,
194 unsigned long arg5,
195 struct smc_result *res);
196
197#endif /* __ASSEMBLER__ */
198
199#endif /* SMC_H */