1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2014, STMicroelectronics International N.V.
4 */
5 #include <assert.h>
6 #include <config.h>
7 #include <kernel/dt_driver.h>
8 #include <malloc.h>
9 #include <stdbool.h>
10 #include <trace.h>
11 #include <kernel/panic.h>
12 #include <util.h>
13
14 #include "misc.h"
15
16 /*
17 * Enable expect LOG macro to enable/disable self tests traces.
18 *
19 * #define LOG DMSG_RAW
20 * #define LOG(...)
21 */
22 #define LOG(...)
23
self_test_add_overflow(void)24 static int self_test_add_overflow(void)
25 {
26 uint32_t r_u32;
27 int32_t r_s32;
28 uintmax_t r_um;
29 intmax_t r_sm;
30
31 if (ADD_OVERFLOW(8U, 0U, &r_s32))
32 return -1;
33 if (r_s32 != 8)
34 return -1;
35 if (ADD_OVERFLOW(32U, 30U, &r_u32))
36 return -1;
37 if (r_u32 != 62)
38 return -1;
39 if (!ADD_OVERFLOW(UINT32_MAX, UINT32_MAX, &r_u32))
40 return -1;
41 if (!ADD_OVERFLOW(UINT32_MAX / 2 + 1, UINT32_MAX / 2 + 1, &r_u32))
42 return -1;
43 if (ADD_OVERFLOW(UINT32_MAX / 2, UINT32_MAX / 2 + 1, &r_u32))
44 return -1;
45 if (r_u32 != UINT32_MAX)
46 return -1;
47
48 if (ADD_OVERFLOW((uint32_t)30, (int32_t)-31, &r_s32))
49 return -1;
50 if (r_s32 != -1)
51 return -1;
52 if (ADD_OVERFLOW((int32_t)30, (int32_t)-31, &r_s32))
53 return -1;
54 if (r_s32 != -1)
55 return -1;
56 if (ADD_OVERFLOW((int32_t)-31, (uint32_t)30, &r_s32))
57 return -1;
58 if (r_s32 != -1)
59 return -1;
60
61 if (ADD_OVERFLOW(INT32_MIN + 1, -1, &r_s32))
62 return -1;
63 if (r_s32 != INT32_MIN)
64 return -1;
65 if (!ADD_OVERFLOW(INT32_MIN, -1, &r_s32))
66 return -1;
67 if (!ADD_OVERFLOW(INT32_MIN + 1, -2, &r_s32))
68 return -1;
69 if (!ADD_OVERFLOW(INT32_MAX, INT32_MAX, &r_s32))
70 return -1;
71 if (ADD_OVERFLOW(INT32_MAX, INT32_MAX, &r_u32))
72 return -1;
73 if (!ADD_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r_sm))
74 return -1;
75 if (ADD_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r_um))
76 return -1;
77 if (!ADD_OVERFLOW(INT32_MAX / 2 + 1, INT32_MAX / 2 + 1, &r_s32))
78 return -1;
79 if (ADD_OVERFLOW(INT32_MAX / 2, INT32_MAX / 2 + 1, &r_s32))
80 return -1;
81 if (r_s32 != INT32_MAX)
82 return -1;
83
84 return 0;
85 }
86
self_test_sub_overflow(void)87 static int self_test_sub_overflow(void)
88 {
89 uint32_t r_u32;
90 int32_t r_s32;
91 intmax_t r_sm;
92
93 if (SUB_OVERFLOW(8U, 1U, &r_s32))
94 return -1;
95 if (r_s32 != 7)
96 return -1;
97 if (SUB_OVERFLOW(32U, 30U, &r_u32))
98 return -1;
99 if (r_u32 != 2)
100 return -1;
101 if (!SUB_OVERFLOW(30U, 31U, &r_u32))
102 return -1;
103
104 if (SUB_OVERFLOW(30, 31, &r_s32))
105 return -1;
106 if (r_s32 != -1)
107 return -1;
108 if (SUB_OVERFLOW(-1, INT32_MAX, &r_s32))
109 return -1;
110 if (r_s32 != INT32_MIN)
111 return -1;
112 if (!SUB_OVERFLOW(-2, INT32_MAX, &r_s32))
113 return -1;
114
115 if (SUB_OVERFLOW((uint32_t)30, (int32_t)-31, &r_s32))
116 return -1;
117 if (r_s32 != 61)
118 return -1;
119 if (SUB_OVERFLOW((int32_t)30, (int32_t)-31, &r_s32))
120 return -1;
121 if (r_s32 != 61)
122 return -1;
123 if (SUB_OVERFLOW((int32_t)-31, (uint32_t)30, &r_s32))
124 return -1;
125 if (r_s32 != -61)
126 return -1;
127 if (SUB_OVERFLOW((int32_t)-31, (int32_t)-30, &r_s32))
128 return -1;
129 if (r_s32 != -1)
130 return -1;
131
132 if (SUB_OVERFLOW((int32_t)31, -(INTMAX_MIN + 1), &r_sm))
133 return -1;
134 if (r_sm != (INTMAX_MIN + 32))
135 return -1;
136
137 return 0;
138 }
139
self_test_mul_unsigned_overflow(void)140 static int self_test_mul_unsigned_overflow(void)
141 {
142 const size_t um_half_shift = sizeof(uintmax_t) * 8 / 2;
143 const uintmax_t um_half_mask = UINTMAX_MAX >> um_half_shift;
144 uint32_t r_u32;
145 uintmax_t r_um;
146
147 if (MUL_OVERFLOW(32, 30, &r_u32))
148 return -1;
149 if (r_u32 != 960)
150 return -1;
151 if (MUL_OVERFLOW(-32, -30, &r_u32))
152 return -1;
153 if (r_u32 != 960)
154 return -1;
155
156 if (MUL_OVERFLOW(UINTMAX_MAX, 1, &r_um))
157 return -1;
158 if (r_um != UINTMAX_MAX)
159 return -1;
160 if (MUL_OVERFLOW(UINTMAX_MAX / 4, 4, &r_um))
161 return -1;
162 if (r_um != (UINTMAX_MAX - 3))
163 return -1;
164 if (!MUL_OVERFLOW(UINTMAX_MAX / 4 + 1, 4, &r_um))
165 return -1;
166 if (!MUL_OVERFLOW(UINTMAX_MAX, UINTMAX_MAX, &r_um))
167 return -1;
168 if (!MUL_OVERFLOW(um_half_mask << um_half_shift,
169 um_half_mask << um_half_shift, &r_um))
170 return -1;
171
172 return 0;
173 }
174
self_test_mul_signed_overflow(void)175 static int self_test_mul_signed_overflow(void)
176 {
177 intmax_t r;
178
179 if (MUL_OVERFLOW(32, -30, &r))
180 return -1;
181 if (r != -960)
182 return -1;
183 if (MUL_OVERFLOW(-32, 30, &r))
184 return -1;
185 if (r != -960)
186 return -1;
187 if (MUL_OVERFLOW(32, 30, &r))
188 return -1;
189 if (r != 960)
190 return -1;
191
192 if (MUL_OVERFLOW(INTMAX_MAX, 1, &r))
193 return -1;
194 if (r != INTMAX_MAX)
195 return -1;
196 if (MUL_OVERFLOW(INTMAX_MAX / 4, 4, &r))
197 return -1;
198 if (r != (INTMAX_MAX - 3))
199 return -1;
200 if (!MUL_OVERFLOW(INTMAX_MAX / 4 + 1, 4, &r))
201 return -1;
202 if (!MUL_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r))
203 return -1;
204 if (MUL_OVERFLOW(INTMAX_MIN + 1, 1, &r))
205 return -1;
206 if (r != INTMAX_MIN + 1)
207 return -1;
208 if (MUL_OVERFLOW(1, INTMAX_MIN + 1, &r))
209 return -1;
210 if (r != INTMAX_MIN + 1)
211 return -1;
212 if (MUL_OVERFLOW(0, INTMAX_MIN, &r))
213 return -1;
214 if (r != 0)
215 return -1;
216 if (MUL_OVERFLOW(1, INTMAX_MIN, &r))
217 return -1;
218 if (r != INTMAX_MIN)
219 return -1;
220
221 return 0;
222 }
223
224 /* test division support. resulting trace shall be manually checked */
self_test_division(void)225 static int self_test_division(void)
226 {
227 signed a, b, c, d;
228 bool r;
229 int ret = 0;
230
231 LOG("");
232 LOG("division tests (division and modulo):");
233 /* get some unpredicted values to prevent compilation optimizations: */
234 /* => use the stack address */
235
236 LOG("- test with unsigned small integers:");
237 a = (signed)((unsigned)(vaddr_t)&a & 0xFFFFF);
238 b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1;
239 c = a / b;
240 d = a % b;
241 r = ((b * c + d) == a);
242 if (!r)
243 ret = -1;
244 LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)",
245 (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c,
246 (unsigned)c);
247 LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a,
248 (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d);
249 LOG(" check results => %s", r ? "ok" : "FAILED !!!");
250 LOG("");
251
252 LOG("- test with signed small integers, negative numerator:");
253 a = (signed)(vaddr_t)&a;
254 b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) - 1;
255 c = a / b;
256 d = a % b;
257 r = ((b * c + d) == a);
258 if (!r)
259 ret = -1;
260 LOG(" 0x%08x / 0x%08x = %d / %d = %d = 0x%x)",
261 (unsigned)a, (unsigned)b, (signed)a, (signed)b, (signed)c,
262 (unsigned)c);
263 LOG(" 0x%08x %% 0x%08x = %d %% %d = %d = 0x%x)", (unsigned)a,
264 (unsigned)b, (signed)a, (signed)b, (signed)d, (unsigned)d);
265 LOG(" check results => %s", r ? "ok" : "FAILED !!!");
266 LOG("");
267
268 LOG("- test with signed small integers, negative denominator:");
269 a = (signed)((unsigned)(vaddr_t)&a & 0xFFFFF);
270 b = -(signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1;
271 c = a / b;
272 d = a % b;
273
274 LOG("- test with unsigned integers, big numerator (> 0x80000000):");
275 a = (signed)(vaddr_t)&a;
276 b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1;
277 c = (signed)((unsigned)a / (unsigned)b);
278 d = (signed)((unsigned)a % (unsigned)b);
279 r = (((unsigned)b * (unsigned)c + (unsigned)d) == (unsigned)a);
280 if (!r)
281 ret = -1;
282 LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)",
283 (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c,
284 (unsigned)c);
285 LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a,
286 (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d);
287 LOG(" check results => %s", r ? "ok" : "FAILED !!!");
288 LOG("");
289
290 LOG("- test with unsigned integers, big num. & denom. (> 0x80000000):");
291 a = (signed)(vaddr_t)&a;
292 b = (signed)((unsigned)(vaddr_t)&a - 1);
293 c = (signed)((unsigned)a / (unsigned)b);
294 d = (signed)((unsigned)a % (unsigned)b);
295 r = (((unsigned)b * (unsigned)c + (unsigned)d) == (unsigned)a);
296 if (!r)
297 ret = -1;
298 LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)",
299 (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c,
300 (unsigned)c);
301 LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a,
302 (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d);
303 LOG(" check results => %s", r ? "ok" : "FAILED !!!");
304 LOG("");
305
306 return ret;
307 }
308
309 /* test malloc support. resulting trace shall be manually checked */
self_test_malloc(void)310 static int self_test_malloc(void)
311 {
312 char *p1 = NULL, *p2 = NULL;
313 int *p3 = NULL, *p4 = NULL;
314 bool r;
315 int ret = 0;
316
317 LOG("malloc tests:");
318 LOG(" p1=%p p2=%p p3=%p p4=%p",
319 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
320 /* test malloc */
321 p1 = malloc(1024);
322 LOG("- p1 = malloc(1024)");
323 p2 = malloc(1024);
324 LOG("- p2 = malloc(1024)");
325 LOG(" p1=%p p2=%p p3=%p p4=%p",
326 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
327 r = (p1 && p2 && malloc_buffer_is_within_alloced(p1, 1024) &&
328 !malloc_buffer_is_within_alloced(p1 + 25, 1000) &&
329 !malloc_buffer_is_within_alloced(p1 - 25, 500) &&
330 malloc_buffer_overlaps_heap(p1 - 25, 500));
331 if (!r)
332 ret = -1;
333 LOG(" => test %s", r ? "ok" : "FAILED");
334 LOG("");
335
336 /* test realloc */
337 p3 = realloc(p1, 3 * 1024);
338 if (p3)
339 p1 = NULL;
340 LOG("- p3 = realloc(p1, 3*1024)");
341 LOG("- free p2");
342 free(p2);
343 p2 = malloc(1024);
344 LOG("- p2 = malloc(1024)");
345 LOG(" p1=%p p2=%p p3=%p p4=%p",
346 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
347 r = (p2 && p3);
348 if (!r)
349 ret = -1;
350 LOG(" => test %s", r ? "ok" : "FAILED");
351 LOG("");
352 LOG("- free p1, p2, p3");
353 free(p1);
354 free(p2);
355 free(p3);
356 p1 = NULL;
357 p2 = NULL;
358 p3 = NULL;
359
360 /* test calloc */
361 p3 = calloc(4, 1024);
362 p4 = calloc(0x100, 1024 * 1024);
363 LOG("- p3 = calloc(4, 1024)");
364 LOG("- p4 = calloc(0x100, 1024*1024) too big: should fail!");
365 LOG(" p1=%p p2=%p p3=%p p4=%p",
366 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
367 r = (p3 && !p4);
368 if (!r)
369 ret = -1;
370 LOG(" => test %s", r ? "ok" : "FAILED");
371 LOG("");
372 LOG("- free p3, p4");
373 free(p3);
374 free(p4);
375 p3 = NULL;
376 p4 = NULL;
377
378 /* test memalign */
379 p3 = memalign(0x1000, 1024);
380 LOG("- p3 = memalign(%d, 1024)", 0x1000);
381 p1 = malloc(1024);
382 LOG("- p1 = malloc(1024)");
383 p4 = memalign(0x100, 512);
384 LOG("- p4 = memalign(%d, 512)", 0x100);
385 LOG(" p1=%p p2=%p p3=%p p4=%p",
386 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
387 r = (p1 && p3 && p4 &&
388 !((vaddr_t)p3 % 0x1000) && !((vaddr_t)p4 % 0x100));
389 if (!r)
390 ret = -1;
391 LOG(" => test %s", r ? "ok" : "FAILED");
392 LOG("");
393 LOG("- free p1, p3, p4");
394 free(p1);
395 free(p3);
396 free(p4);
397 p1 = NULL;
398 p3 = NULL;
399 p4 = NULL;
400
401 /* test memalign with invalid alignments */
402 p3 = memalign(100, 1024);
403 LOG("- p3 = memalign(%d, 1024)", 100);
404 p4 = memalign(0, 1024);
405 LOG("- p4 = memalign(%d, 1024)", 0);
406 LOG(" p1=%p p2=%p p3=%p p4=%p",
407 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
408 r = (!p3 && !p4);
409 if (!r)
410 ret = -1;
411 LOG(" => test %s", r ? "ok" : "FAILED");
412 LOG("");
413 LOG("- free p3, p4");
414 free(p3);
415 free(p4);
416 p3 = NULL;
417 p4 = NULL;
418
419 /* test free(NULL) */
420 LOG("- free NULL");
421 free(NULL);
422 LOG("");
423 LOG("malloc test done");
424
425 return ret;
426 }
427
428 #ifdef CFG_VIRTUALIZATION
429 /* test nex_malloc support. resulting trace shall be manually checked */
self_test_nex_malloc(void)430 static int self_test_nex_malloc(void)
431 {
432 char *p1 = NULL, *p2 = NULL;
433 int *p3 = NULL, *p4 = NULL;
434 bool r;
435 int ret = 0;
436
437 LOG("nex_malloc tests:");
438 LOG(" p1=%p p2=%p p3=%p p4=%p",
439 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
440 /* test malloc */
441 p1 = nex_malloc(1024);
442 LOG("- p1 = nex_malloc(1024)");
443 p2 = nex_malloc(1024);
444 LOG("- p2 = nex_malloc(1024)");
445 LOG(" p1=%p p2=%p p3=%p p4=%p",
446 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
447 r = (p1 && p2 && nex_malloc_buffer_is_within_alloced(p1, 1024) &&
448 !nex_malloc_buffer_is_within_alloced(p1 + 25, 1000) &&
449 !nex_malloc_buffer_is_within_alloced(p1 - 25, 500) &&
450 nex_malloc_buffer_overlaps_heap(p1 - 25, 500));
451 if (!r)
452 ret = -1;
453 LOG(" => test %s", r ? "ok" : "FAILED");
454 LOG("");
455
456 /* test realloc */
457 p3 = nex_realloc(p1, 3 * 1024);
458 if (p3)
459 p1 = NULL;
460 LOG("- p3 = nex_realloc(p1, 3*1024)");
461 LOG("- nex_free p2");
462 nex_free(p2);
463 p2 = nex_malloc(1024);
464 LOG("- p2 = nex_malloc(1024)");
465 LOG(" p1=%p p2=%p p3=%p p4=%p",
466 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
467 r = (p2 && p3);
468 if (!r)
469 ret = -1;
470 LOG(" => test %s", r ? "ok" : "FAILED");
471 LOG("");
472 LOG("- nex_free p1, p2, p3");
473 nex_free(p1);
474 nex_free(p2);
475 nex_free(p3);
476 p1 = NULL;
477 p2 = NULL;
478 p3 = NULL;
479
480 /* test calloc */
481 p3 = nex_calloc(4, 1024);
482 p4 = nex_calloc(0x100, 1024 * 1024);
483 LOG("- p3 = nex_calloc(4, 1024)");
484 LOG("- p4 = nex_calloc(0x100, 1024*1024) too big: should fail!");
485 LOG(" p1=%p p2=%p p3=%p p4=%p",
486 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
487 r = (p3 && !p4);
488 if (!r)
489 ret = -1;
490 LOG(" => test %s", r ? "ok" : "FAILED");
491 LOG("");
492 LOG("- nex_free p3, p4");
493 nex_free(p3);
494 nex_free(p4);
495 p3 = NULL;
496 p4 = NULL;
497
498 /* test memalign */
499 p3 = nex_memalign(0x1000, 1024);
500 LOG("- p3 = nex_memalign(%d, 1024)", 0x1000);
501 p1 = nex_malloc(1024);
502 LOG("- p1 = nex_malloc(1024)");
503 p4 = nex_memalign(0x100, 512);
504 LOG("- p4 = nex_memalign(%d, 512)", 0x100);
505 LOG(" p1=%p p2=%p p3=%p p4=%p",
506 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
507 r = (p1 && p3 && p4 &&
508 !((vaddr_t)p3 % 0x1000) && !((vaddr_t)p4 % 0x100));
509 if (!r)
510 ret = -1;
511 LOG(" => test %s", r ? "ok" : "FAILED");
512 LOG("");
513 LOG("- nex_free p1, p3, p4");
514 nex_free(p1);
515 nex_free(p3);
516 nex_free(p4);
517 p1 = NULL;
518 p3 = NULL;
519 p4 = NULL;
520
521 /* test memalign with invalid alignments */
522 p3 = nex_memalign(100, 1024);
523 LOG("- p3 = nex_memalign(%d, 1024)", 100);
524 p4 = nex_memalign(0, 1024);
525 LOG("- p4 = nex_memalign(%d, 1024)", 0);
526 LOG(" p1=%p p2=%p p3=%p p4=%p",
527 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
528 r = (!p3 && !p4);
529 if (!r)
530 ret = -1;
531 LOG(" => test %s", r ? "ok" : "FAILED");
532 LOG("");
533 LOG("- nex_free p3, p4");
534 nex_free(p3);
535 nex_free(p4);
536 p3 = NULL;
537 p4 = NULL;
538
539 /* test free(NULL) */
540 LOG("- nex_free NULL");
541 nex_free(NULL);
542 LOG("");
543 LOG("nex_malloc test done");
544
545 return ret;
546 }
547 #else /* CFG_VIRTUALIZATION */
self_test_nex_malloc(void)548 static int self_test_nex_malloc(void)
549 {
550 return 0;
551 }
552 #endif
553
554 /* exported entry points for some basic test */
core_self_tests(uint32_t nParamTypes __unused,TEE_Param pParams[TEE_NUM_PARAMS]__unused)555 TEE_Result core_self_tests(uint32_t nParamTypes __unused,
556 TEE_Param pParams[TEE_NUM_PARAMS] __unused)
557 {
558 if (self_test_mul_signed_overflow() || self_test_add_overflow() ||
559 self_test_sub_overflow() || self_test_mul_unsigned_overflow() ||
560 self_test_division() || self_test_malloc() ||
561 self_test_nex_malloc()) {
562 EMSG("some self_test_xxx failed! you should enable local LOG");
563 return TEE_ERROR_GENERIC;
564 }
565 return TEE_SUCCESS;
566 }
567
568 /* Exported entrypoint for dt_driver tests */
core_dt_driver_tests(uint32_t nParamTypes __unused,TEE_Param pParams[TEE_NUM_PARAMS]__unused)569 TEE_Result core_dt_driver_tests(uint32_t nParamTypes __unused,
570 TEE_Param pParams[TEE_NUM_PARAMS] __unused)
571 {
572 if (IS_ENABLED(CFG_DT_DRIVER_EMBEDDED_TEST)) {
573 if (dt_driver_test_status())
574 return TEE_ERROR_GENERIC;
575 } else {
576 IMSG("dt_driver tests are not embedded");
577 }
578
579 return TEE_SUCCESS;
580 }
581