blob: 6d057a6a87a7081b71f90e571d9c2dc8a050fcad [file] [log] [blame]
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +01001/*
Deepika Bhavnanic249d5e2020-02-06 16:29:45 -06002 * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +01003 *
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(
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -060061 "Got {0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx}, \
62 expected {0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx}.\n",
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +010063 ret.ret0, ret.ret1, ret.ret2, ret.ret3,
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -060064 ret.ret4, ret.ret5, ret.ret6, ret.ret7,
65 expect->ret0, expect->ret1, expect->ret2, expect->ret3,
66 expect->ret4, expect->ret5, expect->ret6, expect->ret7);
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +010067 return false;
68 }
69}
70
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +010071/*
72 * Send an SMC with the specified arguments.
73 * Check that the values it returns match the expected ones. The do_check[]
74 * array indicates which ones should be checked and provides some flexibility
Imre Kis1c97f942019-09-23 16:44:03 +020075 * to ignore some of them. Also the allow_zeros[] array lets the values to be
76 * zeroes. allow_zeros[] is only evaluated if do_check[] is true for the given
77 * value.
78 * The two common solutions for preventing data leak from the TEE is to either
79 * preserve the register values or zero them out. Having an expected value and
80 * also allowing zeroes in this function comes handy in this previous case.
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +010081 * If the values do not match, write an error message in the test report.
82 */
83static bool smc_check_match(const smc_args *args, const smc_ret_values *expect,
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -060084 const bool do_check[8], const bool allow_zeros[8])
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +010085{
86 smc_ret_values ret = tftf_smc(args);
87
Imre Kis1c97f942019-09-23 16:44:03 +020088#define CHK_RET(ret, expect, allow_zeros) \
89 ((ret) != (expect) && !((allow_zeros) && (ret) == 0))
90
91 if ((do_check[0] && CHK_RET(ret.ret0, expect->ret0, allow_zeros[0])) ||
92 (do_check[1] && CHK_RET(ret.ret1, expect->ret1, allow_zeros[1])) ||
93 (do_check[2] && CHK_RET(ret.ret2, expect->ret2, allow_zeros[2])) ||
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -060094 (do_check[3] && CHK_RET(ret.ret3, expect->ret3, allow_zeros[3])) ||
95 (do_check[4] && CHK_RET(ret.ret4, expect->ret4, allow_zeros[4])) ||
96 (do_check[5] && CHK_RET(ret.ret5, expect->ret5, allow_zeros[5])) ||
97 (do_check[6] && CHK_RET(ret.ret6, expect->ret6, allow_zeros[6])) ||
98 (do_check[7] && CHK_RET(ret.ret7, expect->ret7, allow_zeros[7]))) {
Imre Kis1c97f942019-09-23 16:44:03 +020099
100#undef CHK_RET
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100101 /*
102 * Build an error message where unchecked SMC return values are
103 * displayed as '*'.
104 */
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600105 char expect_str[8][28];
Imre Kis1c97f942019-09-23 16:44:03 +0200106#define BUILD_STR(_buf, _buf_size, _do_check, _allow_zero, _expect) \
107 do { \
108 if (_do_check) { \
109 if (_allow_zero) { \
110 snprintf(_buf, _buf_size, \
111 "0x%lx or zero", \
112 _expect); \
113 } else { \
114 snprintf(_buf, _buf_size, \
115 "0x%lx", _expect); \
116 } \
117 } else { \
118 _buf[0] = '*'; \
119 _buf[1] = '\0'; \
120 } \
121 } while (0)
122 BUILD_STR(expect_str[0], sizeof(expect_str[0]),
123 do_check[0], allow_zeros[0], expect->ret0);
124 BUILD_STR(expect_str[1], sizeof(expect_str[1]),
125 do_check[1], allow_zeros[1], expect->ret1);
126 BUILD_STR(expect_str[2], sizeof(expect_str[2]),
127 do_check[2], allow_zeros[2], expect->ret2);
128 BUILD_STR(expect_str[3], sizeof(expect_str[3]),
129 do_check[3], allow_zeros[3], expect->ret3);
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600130 BUILD_STR(expect_str[4], sizeof(expect_str[4]),
131 do_check[4], allow_zeros[4], expect->ret4);
132 BUILD_STR(expect_str[5], sizeof(expect_str[5]),
133 do_check[5], allow_zeros[5], expect->ret5);
134 BUILD_STR(expect_str[6], sizeof(expect_str[6]),
135 do_check[6], allow_zeros[6], expect->ret6);
136 BUILD_STR(expect_str[7], sizeof(expect_str[7]),
137 do_check[7], allow_zeros[7], expect->ret7);
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100138#undef BUILD_STR
139 tftf_testcase_printf(
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600140 "Got {0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx}, \
141 expected {%s,%s,%s,%s,%s,%s,%s,%s}.\n",
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100142 ret.ret0, ret.ret1, ret.ret2, ret.ret3,
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600143 ret.ret4, ret.ret5, ret.ret6, ret.ret7,
144 expect_str[0], expect_str[1], expect_str[2], expect_str[3],
145 expect_str[4], expect_str[5], expect_str[6], expect_str[7]);
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100146
147 return false;
148 } else {
149 return true;
150 }
151}
152
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100153/* Exercise SMC32 calling convention with fast SMC calls. */
154test_result_t smc32_fast(void)
155{
156 /* Valid Fast SMC32 using all 4 return values. */
157 const smc_args args1 = { .fid = SMC_STD_SVC_UID };
158 FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
159
160 /* Invalid Fast SMC32. */
161 const smc_args args2 = {
162 make_smc_fid(SMC_TYPE_FAST, SMC_32, OEN_ARM_START, INVALID_FN),
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600163 0x11111111, 0x22222222, 0x33333333, 0x44444444,
164 0x55555555, 0x66666666, 0x77777777 };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100165 const smc_ret_values ret2
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600166 = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333, 0x44444444,
167 0x55555555, 0x66666666, 0x77777777 };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100168 FAIL_IF(!smc_check_eq(&args2, &ret2));
169
170 /* Valid Fast SMC32 using 1 return value. */
171 const smc_args args3
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600172 = { SMC_PSCI_VERSION, 0x44444444, 0x55555555, 0x66666666,
173 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100174 const smc_ret_values ret3
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600175 = { psci_version, 0x44444444, 0x55555555, 0x66666666,
176 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100177 FAIL_IF(!smc_check_eq(&args3, &ret3));
178
179 return TEST_RESULT_SUCCESS;
180}
181
182/* Exercise SMC64 calling convention with yielding SMC calls. */
183test_result_t smc64_yielding(void)
184{
185 /* Valid Fast SMC32 using all 4 return values. */
186 const smc_args args1 = { .fid = SMC_STD_SVC_UID };
187 FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
188
189 /* Invalid function number, SMC64 Yielding. */
190 const smc_args args2 = {
191 make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_ARM_START, INVALID_FN),
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600192 0x11111111, 0x22222222, 0x33333333, 0x44444444,
193 0x55555555, 0x66666666, 0x77777777 };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100194 const smc_ret_values ret2
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600195 = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333, 0x44444444,
196 0x55555555, 0x66666666, 0x77777777 };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100197 FAIL_IF(!smc_check_eq(&args2, &ret2));
198
199 /*
200 * Valid[1] yielding SMC64 using 1 return value.
201 *
202 * [1] Valid from the point of view of the generic SMC handler if the
203 * TSPd is present. In this case, the SMC request gets passed to the
204 * TSPd handler code. The fact that it then gets rejected by the TSPd is
205 * irrelevant here, as we are not trying to test the TSPd nor the TSP.
206 *
207 * In other cases (i.e. AArch64 BL31 with no TSPd support or AArch32
208 * SP_MIN) this test should still fail in the same way, although it
209 * doesn't exercise the same code path in TF-A.
210 */
211 const smc_args args3 = {
212 make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_TOS_START, INVALID_FN),
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600213 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888,
214 0x99999999, 0xaaaaaaaa };
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100215
216 if (is_trusted_os_present(NULL)) {
217 /*
218 * The Trusted OS is free to return any error code in x0 but it
Imre Kis1c97f942019-09-23 16:44:03 +0200219 * should at least preserve or fill by zeroes the values of
220 * x1-x3.
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100221 */
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600222 const smc_ret_values ret3 = { 0, 0x44444444, 0x55555555, 0x66666666,
223 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
224 const bool check[8] = { false, true, true, true, true, true, true, true };
225 const bool allow_zeros[8] = { false, true, true, true,
226 true, true, true, true };
Imre Kis1c97f942019-09-23 16:44:03 +0200227
228 FAIL_IF(!smc_check_match(&args3, &ret3, check, allow_zeros));
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100229 } else {
230 const smc_ret_values ret3
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600231 = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666,
232 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100233 FAIL_IF(!smc_check_eq(&args3, &ret3));
234 }
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100235
236 return TEST_RESULT_SUCCESS;
237}
238
Deepika Bhavnanic249d5e2020-02-06 16:29:45 -0600239#ifndef __aarch64__
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100240static test_result_t smc64_fast_caller32(void)
241{
242 /* Valid Fast SMC32 using all 4 return values. */
243 smc_args args1 = { .fid = SMC_STD_SVC_UID };
244 FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
245
246 /* Invalid SMC function number, Fast SMC64. */
247 const smc_args args2 = {
248 make_smc_fid(SMC_TYPE_FAST, SMC_64, OEN_ARM_START, INVALID_FN),
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600249 0x11111111, 0x22222222, 0x33333333, 0x44444444,
250 0x55555555, 0x66666666, 0x77777777 };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100251 const smc_ret_values ret2
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600252 = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333,
253 0x44444444, 0x55555555, 0x66666666, 0x77777777 };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100254 FAIL_IF(!smc_check_eq(&args2, &ret2));
255
256 /*
257 * Valid SMC function number, Fast SMC64. However, 32-bit callers are
258 * forbidden to use the SMC64 calling convention.
259 */
260 const smc_args args3 = { SMC_PSCI_AFFINITY_INFO_AARCH64,
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600261 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888,
262 0x99999999, 0xaaaaaaaa };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100263 const smc_ret_values ret3
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600264 = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666,
265 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100266 FAIL_IF(!smc_check_eq(&args3, &ret3));
267
268 return TEST_RESULT_SUCCESS;
269}
270#else
271static test_result_t smc64_fast_caller64(void)
272{
273 /* Valid Fast SMC32 using all 4 return values. */
274 smc_args args1 = { .fid = SMC_STD_SVC_UID };
275 FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
276
277 /* Invalid function number, Fast SMC64. */
278 const smc_args args2 = {
279 make_smc_fid(SMC_TYPE_FAST, SMC_64, OEN_ARM_START, INVALID_FN),
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600280 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555,
281 0x66666666, 0x77777777 };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100282 const smc_ret_values ret2
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600283 = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333, 0x44444444,
284 0x55555555, 0x66666666, 0x77777777 };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100285 FAIL_IF(!smc_check_eq(&args2, &ret2));
286
287 /* Valid Fast SMC64 using 1 return value. */
288 const smc_args args3 = { SMC_PSCI_AFFINITY_INFO_AARCH64,
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600289 0x44444444, 0x55555555, 0x66666666, 0x77777777,
290 0x88888888, 0x99999999, 0xaaaaaaaa };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100291 const smc_ret_values ret3
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600292 = { PSCI_E_INVALID_PARAMS, 0x44444444, 0x55555555, 0x66666666,
293 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100294 FAIL_IF(!smc_check_eq(&args3, &ret3));
295
296 return TEST_RESULT_SUCCESS;
297}
Deepika Bhavnanic249d5e2020-02-06 16:29:45 -0600298#endif /* !__aarch64__ */
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100299
300/* Exercise SMC64 calling convention with fast SMC calls. */
301test_result_t smc64_fast(void)
302{
Deepika Bhavnanic249d5e2020-02-06 16:29:45 -0600303#ifndef __aarch64__
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100304 return smc64_fast_caller32();
305#else
306 return smc64_fast_caller64();
307#endif
308}
309
310/* Exercise SMC32 calling convention with yielding SMC calls. */
311test_result_t smc32_yielding(void)
312{
313 /* Valid Fast SMC32 using all 4 return values. */
314 const smc_args args1 = { .fid = SMC_STD_SVC_UID };
315 FAIL_IF(!smc_check_eq(&args1, &std_svc_uuid));
316
317 /* Invalid function number, SMC32 Yielding. */
318 const smc_args args2 = {
319 make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_ARM_START, INVALID_FN),
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600320 0x11111111, 0x22222222, 0x33333333, 0x44444444,
321 0x55555555, 0x66666666, 0x77777777 };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100322 const smc_ret_values ret2
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600323 = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333, 0x44444444,
324 0x55555555, 0x66666666, 0x77777777 };
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100325 FAIL_IF(!smc_check_eq(&args2, &ret2));
326
327 /*
328 * Valid[1] yielding SMC32 using 1 return value.
329 *
330 * [1] Valid from the point of view of the generic SMC handler if a
331 * secure payload dispatcher handling this SMC range is present. In this
332 * case, the SMC request gets passed to the dispatcher handler code. The
333 * fact that it then gets rejected by the dispatcher is irrelevant here,
334 * as we are not trying to test the dispatcher nor the secure payload.
335 *
336 * In BL31 has no SPD support, this test should still fail in the same
337 * way, although it doesn't exercise the same code path in TF-A.
338 */
339 const smc_args args3 = {
340 make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_TOS_START, INVALID_FN),
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600341 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888,
342 0x99999999, 0xaaaaaaaa };
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100343
344 if (is_trusted_os_present(NULL)) {
345 /*
346 * The Trusted OS is free to return any error code in x0 but it
Imre Kis1c97f942019-09-23 16:44:03 +0200347 * should at least preserve or fill by zeroes the values of
348 * x1-x3.
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100349 */
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600350 const smc_ret_values ret3 = { 0, 0x44444444, 0x55555555, 0x66666666,
351 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
352 const bool check[8] = { false, true, true, true, true, true, true, true };
353 const bool allow_zeros[8] = { false, true, true, true,
354 true, true, true, true };
Imre Kis1c97f942019-09-23 16:44:03 +0200355
356 FAIL_IF(!smc_check_match(&args3, &ret3, check, allow_zeros));
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100357 } else {
358 const smc_ret_values ret3
Madhukar Pappireddyc783c0b2019-11-14 23:52:37 -0600359 = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666,
360 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
Sandrine Bailleuxc5d315e2019-01-07 10:44:32 +0100361 FAIL_IF(!smc_check_eq(&args3, &ret3));
362 }
Sandrine Bailleux3f556eb2018-11-16 14:00:40 +0100363
364 return TEST_RESULT_SUCCESS;
365}
366