blob: 366509bb482e44e4c6b4b852dd9ac3f4cc6efd22 [file] [log] [blame]
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +01001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <psci.h>
8#include <smccc.h>
9#include <std_svc.h>
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +010010#include <stdio.h>
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +010011#include <string.h>
12#include <tftf_lib.h>
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +010013#include <trusted_os.h>
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +010014#include <tsp.h>
15#include <utils_def.h>
16
17/* An invalid SMC function number. */
18#define INVALID_FN 0x666
19
20/* PSCI version returned by TF-A. */
21static const uint32_t psci_version = PSCI_VERSION(PSCI_MAJOR_VER,
22 PSCI_MINOR_VER);
23
24/* UUID of the standard service in TF-A. */
25static const smc_ret_values std_svc_uuid = {
26 0x108d905b, 0x47e8f863, 0xfbc02dae, 0xe2f64156
27};
28
29/*
30 * Build an SMC function ID given its type (fast/yielding), calling convention,
31 * owning entity number and function number.
32 */
33static inline uint32_t make_smc_fid(unsigned int type, unsigned int cc,
34 unsigned int oen, unsigned int func_num)
35{
36 return (type << FUNCID_TYPE_SHIFT) | (cc << FUNCID_CC_SHIFT)
37 | (oen << FUNCID_OEN_SHIFT) | (func_num << FUNCID_NUM_SHIFT);
38}
39
40/* Exit the test if the specified condition holds true. */
41#define FAIL_IF(_cond) \
42 do { \
43 if ((_cond)) { \
44 return TEST_RESULT_FAIL; \
45 } \
46 } while (0)
47
48/*
49 * Send an SMC with the specified arguments.
50 * Check that the values it returns match the expected ones. If not, write an
51 * error message in the test report.
52 */
53static bool smc_check_eq(const smc_args *args, const smc_ret_values *expect)
54{
55 smc_ret_values ret = tftf_smc(args);
56
57 if (memcmp(&ret, expect, sizeof(smc_ret_values)) == 0) {
58 return true;
59 } else {
60 tftf_testcase_printf(
61 "Got {0x%lx,0x%lx,0x%lx,0x%lx}, expected {0x%lx,0x%lx,0x%lx,0x%lx}.\n",
62 ret.ret0, ret.ret1, ret.ret2, ret.ret3,
63 expect->ret0, expect->ret1, expect->ret2, expect->ret3);
64 return false;
65 }
66}
67
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +010068/*
69 * Send an SMC with the specified arguments.
70 * Check that the values it returns match the expected ones. The do_check[]
71 * array indicates which ones should be checked and provides some flexibility
72 * to ignore some of them.
73 * If the values do not match, write an error message in the test report.
74 */
75static bool smc_check_match(const smc_args *args, const smc_ret_values *expect,
76 const bool do_check[4])
77{
78 smc_ret_values ret = tftf_smc(args);
79
80 if ((do_check[0] && (ret.ret0 != expect->ret0)) ||
81 (do_check[1] && (ret.ret1 != expect->ret1)) ||
82 (do_check[2] && (ret.ret2 != expect->ret2)) ||
83 (do_check[3] && (ret.ret3 != expect->ret3))) {
84 /*
85 * Build an error message where unchecked SMC return values are
86 * displayed as '*'.
87 */
88 char expect_str[4][20];
89#define BUILD_STR(_buf, _do_check, _expect) \
90 if (_do_check) { \
91 snprintf(_buf, 20, "0x%lx", _expect); \
92 } else { \
93 strncpy(_buf, "*", 2); \
94 }
95 BUILD_STR(expect_str[0], do_check[0], expect->ret0);
96 BUILD_STR(expect_str[1], do_check[1], expect->ret1);
97 BUILD_STR(expect_str[2], do_check[2], expect->ret2);
98 BUILD_STR(expect_str[3], do_check[3], expect->ret3);
99#undef BUILD_STR
100 tftf_testcase_printf(
101 "Got {0x%lx,0x%lx,0x%lx,0x%lx}, expected {%s,%s,%s,%s}.\n",
102 ret.ret0, ret.ret1, ret.ret2, ret.ret3,
103 expect_str[0], expect_str[1], expect_str[2], expect_str[3]);
104
105 return false;
106 } else {
107 return true;
108 }
109}
110
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100111/* Exercise SMC32 calling convention with fast SMC calls. */
112test_result_t smc32_fast(void)
113{
114 /* Valid Fast SMC32 using all 4 return values. */
115 const smc_args args1 = { .fid = SMC_STD_SVC_UID };
116 FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
117
118 /* Invalid Fast SMC32. */
119 const smc_args args2 = {
120 make_smc_fid(SMC_TYPE_FAST, SMC_32, OEN_ARM_START, INVALID_FN),
121 0x11111111, 0x22222222, 0x33333333 };
122 const smc_ret_values ret2
123 = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
124 FAIL_IF(!smc_check_eq(&args2, &ret2));
125
126 /* Valid Fast SMC32 using 1 return value. */
127 const smc_args args3
128 = { SMC_PSCI_VERSION, 0x44444444, 0x55555555, 0x66666666 };
129 const smc_ret_values ret3
130 = { psci_version, 0x44444444, 0x55555555, 0x66666666 };
131 FAIL_IF(!smc_check_eq(&args3, &ret3));
132
133 return TEST_RESULT_SUCCESS;
134}
135
136/* Exercise SMC64 calling convention with yielding SMC calls. */
137test_result_t smc64_yielding(void)
138{
139 /* Valid Fast SMC32 using all 4 return values. */
140 const smc_args args1 = { .fid = SMC_STD_SVC_UID };
141 FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
142
143 /* Invalid function number, SMC64 Yielding. */
144 const smc_args args2 = {
145 make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_ARM_START, INVALID_FN),
146 0x11111111, 0x22222222, 0x33333333 };
147 const smc_ret_values ret2
148 = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
149 FAIL_IF(!smc_check_eq(&args2, &ret2));
150
151 /*
152 * Valid[1] yielding SMC64 using 1 return value.
153 *
154 * [1] Valid from the point of view of the generic SMC handler if the
155 * TSPd is present. In this case, the SMC request gets passed to the
156 * TSPd handler code. The fact that it then gets rejected by the TSPd is
157 * irrelevant here, as we are not trying to test the TSPd nor the TSP.
158 *
159 * In other cases (i.e. AArch64 BL31 with no TSPd support or AArch32
160 * SP_MIN) this test should still fail in the same way, although it
161 * doesn't exercise the same code path in TF-A.
162 */
163 const smc_args args3 = {
164 make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_TOS_START, INVALID_FN),
165 0x44444444, 0x55555555, 0x66666666 };
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100166
167 if (is_trusted_os_present(NULL)) {
168 /*
169 * The Trusted OS is free to return any error code in x0 but it
170 * should at least preserve the values of x1-x3.
171 */
172 const smc_ret_values ret3 = { 0, 0x44444444, 0x55555555, 0x66666666 };
173 const bool check[4] = { false, true, true, true };
174 FAIL_IF(!smc_check_match(&args3, &ret3, check));
175 } else {
176 const smc_ret_values ret3
177 = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
178 FAIL_IF(!smc_check_eq(&args3, &ret3));
179 }
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100180
181 return TEST_RESULT_SUCCESS;
182}
183
184#ifdef AARCH32
185static test_result_t smc64_fast_caller32(void)
186{
187 /* Valid Fast SMC32 using all 4 return values. */
188 smc_args args1 = { .fid = SMC_STD_SVC_UID };
189 FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
190
191 /* Invalid SMC function number, Fast SMC64. */
192 const smc_args args2 = {
193 make_smc_fid(SMC_TYPE_FAST, SMC_64, OEN_ARM_START, INVALID_FN),
194 0x11111111, 0x22222222, 0x33333333 };
195 const smc_ret_values ret2
196 = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
197 FAIL_IF(!smc_check_eq(&args2, &ret2));
198
199 /*
200 * Valid SMC function number, Fast SMC64. However, 32-bit callers are
201 * forbidden to use the SMC64 calling convention.
202 */
203 const smc_args args3 = { SMC_PSCI_AFFINITY_INFO_AARCH64,
204 0x44444444, 0x55555555, 0x66666666 };
205 const smc_ret_values ret3
206 = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
207 FAIL_IF(!smc_check_eq(&args3, &ret3));
208
209 return TEST_RESULT_SUCCESS;
210}
211#else
212static test_result_t smc64_fast_caller64(void)
213{
214 /* Valid Fast SMC32 using all 4 return values. */
215 smc_args args1 = { .fid = SMC_STD_SVC_UID };
216 FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
217
218 /* Invalid function number, Fast SMC64. */
219 const smc_args args2 = {
220 make_smc_fid(SMC_TYPE_FAST, SMC_64, OEN_ARM_START, INVALID_FN),
221 0x11111111, 0x22222222, 0x33333333 };
222 const smc_ret_values ret2
223 = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
224 FAIL_IF(!smc_check_eq(&args2, &ret2));
225
226 /* Valid Fast SMC64 using 1 return value. */
227 const smc_args args3 = { SMC_PSCI_AFFINITY_INFO_AARCH64,
228 0x44444444, 0x55555555, 0x66666666 };
229 const smc_ret_values ret3
230 = { PSCI_E_INVALID_PARAMS, 0x44444444, 0x55555555, 0x66666666 };
231 FAIL_IF(!smc_check_eq(&args3, &ret3));
232
233 return TEST_RESULT_SUCCESS;
234}
235#endif /* AARCH32 */
236
237/* Exercise SMC64 calling convention with fast SMC calls. */
238test_result_t smc64_fast(void)
239{
240#ifdef AARCH32
241 return smc64_fast_caller32();
242#else
243 return smc64_fast_caller64();
244#endif
245}
246
247/* Exercise SMC32 calling convention with yielding SMC calls. */
248test_result_t smc32_yielding(void)
249{
250 /* Valid Fast SMC32 using all 4 return values. */
251 const smc_args args1 = { .fid = SMC_STD_SVC_UID };
252 FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
253
254 /* Invalid function number, SMC32 Yielding. */
255 const smc_args args2 = {
256 make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_ARM_START, INVALID_FN),
257 0x11111111, 0x22222222, 0x33333333 };
258 const smc_ret_values ret2
259 = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
260 FAIL_IF(!smc_check_eq(&args2, &ret2));
261
262 /*
263 * Valid[1] yielding SMC32 using 1 return value.
264 *
265 * [1] Valid from the point of view of the generic SMC handler if a
266 * secure payload dispatcher handling this SMC range is present. In this
267 * case, the SMC request gets passed to the dispatcher handler code. The
268 * fact that it then gets rejected by the dispatcher is irrelevant here,
269 * as we are not trying to test the dispatcher nor the secure payload.
270 *
271 * In BL31 has no SPD support, this test should still fail in the same
272 * way, although it doesn't exercise the same code path in TF-A.
273 */
274 const smc_args args3 = {
275 make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_TOS_START, INVALID_FN),
276 0x44444444, 0x55555555, 0x66666666 };
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100277
278 if (is_trusted_os_present(NULL)) {
279 /*
280 * The Trusted OS is free to return any error code in x0 but it
281 * should at least preserve the values of x1-x3.
282 */
283 const smc_ret_values ret3 = { 0, 0x44444444, 0x55555555, 0x66666666 };
284 const bool check[4] = { false, true, true, true };
285 FAIL_IF(!smc_check_match(&args3, &ret3, check));
286 } else {
287 const smc_ret_values ret3
288 = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
289 FAIL_IF(!smc_check_eq(&args3, &ret3));
290 }
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100291
292 return TEST_RESULT_SUCCESS;
293}
294