1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2014, STMicroelectronics International N.V.
4 * Copyright (c) 2025, Linaro Limited.
5 */
6 #include <assert.h>
7 #include <config.h>
8 #include <kernel/asan.h>
9 #include <kernel/dt_driver.h>
10 #include <kernel/linker.h>
11 #include <kernel/panic.h>
12 #include <malloc.h>
13 #include <mm/core_memprot.h>
14 #include <setjmp.h>
15 #include <stdbool.h>
16 #include <trace.h>
17 #include <util.h>
18
19 #include "misc.h"
20
21 /*
22 * Enable expect LOG macro to enable/disable self tests traces.
23 *
24 * #define LOG DMSG_RAW
25 * #define LOG(...)
26 */
27 #define LOG(...)
28
self_test_add_overflow(void)29 static int self_test_add_overflow(void)
30 {
31 uint32_t r_u32;
32 int32_t r_s32;
33 uintmax_t r_um;
34 intmax_t r_sm;
35
36 if (ADD_OVERFLOW(8U, 0U, &r_s32))
37 return -1;
38 if (r_s32 != 8)
39 return -1;
40 if (ADD_OVERFLOW(32U, 30U, &r_u32))
41 return -1;
42 if (r_u32 != 62)
43 return -1;
44 if (!ADD_OVERFLOW(UINT32_MAX, UINT32_MAX, &r_u32))
45 return -1;
46 if (!ADD_OVERFLOW(UINT32_MAX / 2 + 1, UINT32_MAX / 2 + 1, &r_u32))
47 return -1;
48 if (ADD_OVERFLOW(UINT32_MAX / 2, UINT32_MAX / 2 + 1, &r_u32))
49 return -1;
50 if (r_u32 != UINT32_MAX)
51 return -1;
52
53 if (ADD_OVERFLOW((uint32_t)30, (int32_t)-31, &r_s32))
54 return -1;
55 if (r_s32 != -1)
56 return -1;
57 if (ADD_OVERFLOW((int32_t)30, (int32_t)-31, &r_s32))
58 return -1;
59 if (r_s32 != -1)
60 return -1;
61 if (ADD_OVERFLOW((int32_t)-31, (uint32_t)30, &r_s32))
62 return -1;
63 if (r_s32 != -1)
64 return -1;
65
66 if (ADD_OVERFLOW(INT32_MIN + 1, -1, &r_s32))
67 return -1;
68 if (r_s32 != INT32_MIN)
69 return -1;
70 if (!ADD_OVERFLOW(INT32_MIN, -1, &r_s32))
71 return -1;
72 if (!ADD_OVERFLOW(INT32_MIN + 1, -2, &r_s32))
73 return -1;
74 if (!ADD_OVERFLOW(INT32_MAX, INT32_MAX, &r_s32))
75 return -1;
76 if (ADD_OVERFLOW(INT32_MAX, INT32_MAX, &r_u32))
77 return -1;
78 if (!ADD_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r_sm))
79 return -1;
80 if (ADD_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r_um))
81 return -1;
82 if (!ADD_OVERFLOW(INT32_MAX / 2 + 1, INT32_MAX / 2 + 1, &r_s32))
83 return -1;
84 if (ADD_OVERFLOW(INT32_MAX / 2, INT32_MAX / 2 + 1, &r_s32))
85 return -1;
86 if (r_s32 != INT32_MAX)
87 return -1;
88
89 return 0;
90 }
91
self_test_sub_overflow(void)92 static int self_test_sub_overflow(void)
93 {
94 uint32_t r_u32;
95 int32_t r_s32;
96 intmax_t r_sm;
97
98 if (SUB_OVERFLOW(8U, 1U, &r_s32))
99 return -1;
100 if (r_s32 != 7)
101 return -1;
102 if (SUB_OVERFLOW(32U, 30U, &r_u32))
103 return -1;
104 if (r_u32 != 2)
105 return -1;
106 if (!SUB_OVERFLOW(30U, 31U, &r_u32))
107 return -1;
108
109 if (SUB_OVERFLOW(30, 31, &r_s32))
110 return -1;
111 if (r_s32 != -1)
112 return -1;
113 if (SUB_OVERFLOW(-1, INT32_MAX, &r_s32))
114 return -1;
115 if (r_s32 != INT32_MIN)
116 return -1;
117 if (!SUB_OVERFLOW(-2, INT32_MAX, &r_s32))
118 return -1;
119
120 if (SUB_OVERFLOW((uint32_t)30, (int32_t)-31, &r_s32))
121 return -1;
122 if (r_s32 != 61)
123 return -1;
124 if (SUB_OVERFLOW((int32_t)30, (int32_t)-31, &r_s32))
125 return -1;
126 if (r_s32 != 61)
127 return -1;
128 if (SUB_OVERFLOW((int32_t)-31, (uint32_t)30, &r_s32))
129 return -1;
130 if (r_s32 != -61)
131 return -1;
132 if (SUB_OVERFLOW((int32_t)-31, (int32_t)-30, &r_s32))
133 return -1;
134 if (r_s32 != -1)
135 return -1;
136
137 if (SUB_OVERFLOW((int32_t)31, -(INTMAX_MIN + 1), &r_sm))
138 return -1;
139 if (r_sm != (INTMAX_MIN + 32))
140 return -1;
141
142 return 0;
143 }
144
self_test_mul_unsigned_overflow(void)145 static int self_test_mul_unsigned_overflow(void)
146 {
147 const size_t um_half_shift = sizeof(uintmax_t) * 8 / 2;
148 const uintmax_t um_half_mask = UINTMAX_MAX >> um_half_shift;
149 uint32_t r_u32;
150 uintmax_t r_um;
151
152 if (MUL_OVERFLOW(32, 30, &r_u32))
153 return -1;
154 if (r_u32 != 960)
155 return -1;
156 if (MUL_OVERFLOW(-32, -30, &r_u32))
157 return -1;
158 if (r_u32 != 960)
159 return -1;
160
161 if (MUL_OVERFLOW(UINTMAX_MAX, 1, &r_um))
162 return -1;
163 if (r_um != UINTMAX_MAX)
164 return -1;
165 if (MUL_OVERFLOW(UINTMAX_MAX / 4, 4, &r_um))
166 return -1;
167 if (r_um != (UINTMAX_MAX - 3))
168 return -1;
169 if (!MUL_OVERFLOW(UINTMAX_MAX / 4 + 1, 4, &r_um))
170 return -1;
171 if (!MUL_OVERFLOW(UINTMAX_MAX, UINTMAX_MAX, &r_um))
172 return -1;
173 if (!MUL_OVERFLOW(um_half_mask << um_half_shift,
174 um_half_mask << um_half_shift, &r_um))
175 return -1;
176
177 return 0;
178 }
179
self_test_mul_signed_overflow(void)180 static int self_test_mul_signed_overflow(void)
181 {
182 intmax_t r;
183
184 if (MUL_OVERFLOW(32, -30, &r))
185 return -1;
186 if (r != -960)
187 return -1;
188 if (MUL_OVERFLOW(-32, 30, &r))
189 return -1;
190 if (r != -960)
191 return -1;
192 if (MUL_OVERFLOW(32, 30, &r))
193 return -1;
194 if (r != 960)
195 return -1;
196
197 if (MUL_OVERFLOW(INTMAX_MAX, 1, &r))
198 return -1;
199 if (r != INTMAX_MAX)
200 return -1;
201 if (MUL_OVERFLOW(INTMAX_MAX / 4, 4, &r))
202 return -1;
203 if (r != (INTMAX_MAX - 3))
204 return -1;
205 if (!MUL_OVERFLOW(INTMAX_MAX / 4 + 1, 4, &r))
206 return -1;
207 if (!MUL_OVERFLOW(INTMAX_MAX, INTMAX_MAX, &r))
208 return -1;
209 if (MUL_OVERFLOW(INTMAX_MIN + 1, 1, &r))
210 return -1;
211 if (r != INTMAX_MIN + 1)
212 return -1;
213 if (MUL_OVERFLOW(1, INTMAX_MIN + 1, &r))
214 return -1;
215 if (r != INTMAX_MIN + 1)
216 return -1;
217 if (MUL_OVERFLOW(0, INTMAX_MIN, &r))
218 return -1;
219 if (r != 0)
220 return -1;
221 if (MUL_OVERFLOW(1, INTMAX_MIN, &r))
222 return -1;
223 if (r != INTMAX_MIN)
224 return -1;
225
226 return 0;
227 }
228
229 /* test division support. resulting trace shall be manually checked */
self_test_division(void)230 static int self_test_division(void)
231 {
232 signed a, b, c, d;
233 bool r;
234 int ret = 0;
235
236 LOG("");
237 LOG("division tests (division and modulo):");
238 /* get some unpredicted values to prevent compilation optimizations: */
239 /* => use the stack address */
240
241 LOG("- test with unsigned small integers:");
242 a = (signed)((unsigned)(vaddr_t)&a & 0xFFFFF);
243 b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1;
244 c = a / b;
245 d = a % b;
246 r = ((b * c + d) == a);
247 if (!r)
248 ret = -1;
249 LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)",
250 (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c,
251 (unsigned)c);
252 LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a,
253 (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d);
254 LOG(" check results => %s", r ? "ok" : "FAILED !!!");
255 LOG("");
256
257 LOG("- test with signed small integers, negative numerator:");
258 a = (signed)(vaddr_t)&a;
259 b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) - 1;
260 c = a / b;
261 d = a % b;
262 r = ((b * c + d) == a);
263 if (!r)
264 ret = -1;
265 LOG(" 0x%08x / 0x%08x = %d / %d = %d = 0x%x)",
266 (unsigned)a, (unsigned)b, (signed)a, (signed)b, (signed)c,
267 (unsigned)c);
268 LOG(" 0x%08x %% 0x%08x = %d %% %d = %d = 0x%x)", (unsigned)a,
269 (unsigned)b, (signed)a, (signed)b, (signed)d, (unsigned)d);
270 LOG(" check results => %s", r ? "ok" : "FAILED !!!");
271 LOG("");
272
273 LOG("- test with signed small integers, negative denominator:");
274 a = (signed)((unsigned)(vaddr_t)&a & 0xFFFFF);
275 b = -(signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1;
276 c = a / b;
277 d = a % b;
278
279 LOG("- test with unsigned integers, big numerator (> 0x80000000):");
280 a = (signed)(vaddr_t)&a;
281 b = (signed)((unsigned)(vaddr_t)&b & 0x00FFF) + 1;
282 c = (signed)((unsigned)a / (unsigned)b);
283 d = (signed)((unsigned)a % (unsigned)b);
284 r = (((unsigned)b * (unsigned)c + (unsigned)d) == (unsigned)a);
285 if (!r)
286 ret = -1;
287 LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)",
288 (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c,
289 (unsigned)c);
290 LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a,
291 (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d);
292 LOG(" check results => %s", r ? "ok" : "FAILED !!!");
293 LOG("");
294
295 LOG("- test with unsigned integers, big num. & denom. (> 0x80000000):");
296 a = (signed)(vaddr_t)&a;
297 b = (signed)((unsigned)(vaddr_t)&a - 1);
298 c = (signed)((unsigned)a / (unsigned)b);
299 d = (signed)((unsigned)a % (unsigned)b);
300 r = (((unsigned)b * (unsigned)c + (unsigned)d) == (unsigned)a);
301 if (!r)
302 ret = -1;
303 LOG(" 0x%08x / 0x%08x = %u / %u = %u = 0x%x)",
304 (unsigned)a, (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)c,
305 (unsigned)c);
306 LOG(" 0x%08x %% 0x%08x = %u %% %u = %u = 0x%x)", (unsigned)a,
307 (unsigned)b, (unsigned)a, (unsigned)b, (unsigned)d, (unsigned)d);
308 LOG(" check results => %s", r ? "ok" : "FAILED !!!");
309 LOG("");
310
311 return ret;
312 }
313
314 /* test malloc support. resulting trace shall be manually checked */
self_test_malloc(void)315 static int self_test_malloc(void)
316 {
317 char *p1 = NULL, *p2 = NULL;
318 int *p3 = NULL, *p4 = NULL;
319 bool r;
320 int ret = 0;
321
322 LOG("malloc tests:");
323 LOG(" p1=%p p2=%p p3=%p p4=%p",
324 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
325 /* test malloc */
326 p1 = malloc(1024);
327 LOG("- p1 = malloc(1024)");
328 p2 = malloc(1024);
329 LOG("- p2 = malloc(1024)");
330 LOG(" p1=%p p2=%p p3=%p p4=%p",
331 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
332 r = (p1 && p2 && malloc_buffer_is_within_alloced(p1, 1024) &&
333 !malloc_buffer_is_within_alloced(p1 + 25, 1000) &&
334 !malloc_buffer_is_within_alloced(p1 - 25, 500) &&
335 malloc_buffer_overlaps_heap(p1 - 25, 500));
336 if (!r)
337 ret = -1;
338 LOG(" => test %s", r ? "ok" : "FAILED");
339 LOG("");
340
341 /* test realloc */
342 p3 = realloc(p1, 3 * 1024);
343 if (p3)
344 p1 = NULL;
345 LOG("- p3 = realloc(p1, 3*1024)");
346 LOG("- free p2");
347 free(p2);
348 p2 = malloc(1024);
349 LOG("- p2 = malloc(1024)");
350 LOG(" p1=%p p2=%p p3=%p p4=%p",
351 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
352 r = (p2 && p3);
353 if (!r)
354 ret = -1;
355 LOG(" => test %s", r ? "ok" : "FAILED");
356 LOG("");
357 LOG("- free p1, p2, p3");
358 free(p1);
359 free(p2);
360 free(p3);
361 p1 = NULL;
362 p2 = NULL;
363 p3 = NULL;
364
365 /* test calloc */
366 p3 = calloc(4, 1024);
367 p4 = calloc(0x100, 1024 * 1024);
368 LOG("- p3 = calloc(4, 1024)");
369 LOG("- p4 = calloc(0x100, 1024*1024) too big: should fail!");
370 LOG(" p1=%p p2=%p p3=%p p4=%p",
371 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
372 r = (p3 && !p4);
373 if (!r)
374 ret = -1;
375 LOG(" => test %s", r ? "ok" : "FAILED");
376 LOG("");
377 LOG("- free p3, p4");
378 free(p3);
379 free(p4);
380 p3 = NULL;
381 p4 = NULL;
382
383 /* test memalign */
384 p3 = memalign(0x1000, 1024);
385 LOG("- p3 = memalign(%d, 1024)", 0x1000);
386 p1 = malloc(1024);
387 LOG("- p1 = malloc(1024)");
388 p4 = memalign(0x100, 512);
389 LOG("- p4 = memalign(%d, 512)", 0x100);
390 LOG(" p1=%p p2=%p p3=%p p4=%p",
391 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
392 r = (p1 && p3 && p4 &&
393 !((vaddr_t)p3 % 0x1000) && !((vaddr_t)p4 % 0x100));
394 if (!r)
395 ret = -1;
396 LOG(" => test %s", r ? "ok" : "FAILED");
397 LOG("");
398 LOG("- free p1, p3, p4");
399 free(p1);
400 free(p3);
401 free(p4);
402 p1 = NULL;
403 p3 = NULL;
404 p4 = NULL;
405
406 /* test memalign with invalid alignments */
407 p3 = memalign(100, 1024);
408 LOG("- p3 = memalign(%d, 1024)", 100);
409 p4 = memalign(0, 1024);
410 LOG("- p4 = memalign(%d, 1024)", 0);
411 LOG(" p1=%p p2=%p p3=%p p4=%p",
412 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
413 r = (!p3 && !p4);
414 if (!r)
415 ret = -1;
416 LOG(" => test %s", r ? "ok" : "FAILED");
417 LOG("");
418 LOG("- free p3, p4");
419 free(p3);
420 free(p4);
421 p3 = NULL;
422 p4 = NULL;
423
424 /* test free(NULL) */
425 LOG("- free NULL");
426 free(NULL);
427 LOG("");
428 LOG("malloc test done");
429
430 return ret;
431 }
432
433 #ifdef CFG_NS_VIRTUALIZATION
434 /* test nex_malloc support. resulting trace shall be manually checked */
self_test_nex_malloc(void)435 static int self_test_nex_malloc(void)
436 {
437 char *p1 = NULL, *p2 = NULL;
438 int *p3 = NULL, *p4 = NULL;
439 bool r;
440 int ret = 0;
441
442 LOG("nex_malloc tests:");
443 LOG(" p1=%p p2=%p p3=%p p4=%p",
444 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
445 /* test malloc */
446 p1 = nex_malloc(1024);
447 LOG("- p1 = nex_malloc(1024)");
448 p2 = nex_malloc(1024);
449 LOG("- p2 = nex_malloc(1024)");
450 LOG(" p1=%p p2=%p p3=%p p4=%p",
451 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
452 r = (p1 && p2 && nex_malloc_buffer_is_within_alloced(p1, 1024) &&
453 !nex_malloc_buffer_is_within_alloced(p1 + 25, 1000) &&
454 !nex_malloc_buffer_is_within_alloced(p1 - 25, 500) &&
455 nex_malloc_buffer_overlaps_heap(p1 - 25, 500));
456 if (!r)
457 ret = -1;
458 LOG(" => test %s", r ? "ok" : "FAILED");
459 LOG("");
460
461 /* test realloc */
462 p3 = nex_realloc(p1, 3 * 1024);
463 if (p3)
464 p1 = NULL;
465 LOG("- p3 = nex_realloc(p1, 3*1024)");
466 LOG("- nex_free p2");
467 nex_free(p2);
468 p2 = nex_malloc(1024);
469 LOG("- p2 = nex_malloc(1024)");
470 LOG(" p1=%p p2=%p p3=%p p4=%p",
471 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
472 r = (p2 && p3);
473 if (!r)
474 ret = -1;
475 LOG(" => test %s", r ? "ok" : "FAILED");
476 LOG("");
477 LOG("- nex_free p1, p2, p3");
478 nex_free(p1);
479 nex_free(p2);
480 nex_free(p3);
481 p1 = NULL;
482 p2 = NULL;
483 p3 = NULL;
484
485 /* test calloc */
486 p3 = nex_calloc(4, 1024);
487 p4 = nex_calloc(0x100, 1024 * 1024);
488 LOG("- p3 = nex_calloc(4, 1024)");
489 LOG("- p4 = nex_calloc(0x100, 1024*1024) too big: should fail!");
490 LOG(" p1=%p p2=%p p3=%p p4=%p",
491 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
492 r = (p3 && !p4);
493 if (!r)
494 ret = -1;
495 LOG(" => test %s", r ? "ok" : "FAILED");
496 LOG("");
497 LOG("- nex_free p3, p4");
498 nex_free(p3);
499 nex_free(p4);
500 p3 = NULL;
501 p4 = NULL;
502
503 /* test memalign */
504 p3 = nex_memalign(0x1000, 1024);
505 LOG("- p3 = nex_memalign(%d, 1024)", 0x1000);
506 p1 = nex_malloc(1024);
507 LOG("- p1 = nex_malloc(1024)");
508 p4 = nex_memalign(0x100, 512);
509 LOG("- p4 = nex_memalign(%d, 512)", 0x100);
510 LOG(" p1=%p p2=%p p3=%p p4=%p",
511 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
512 r = (p1 && p3 && p4 &&
513 !((vaddr_t)p3 % 0x1000) && !((vaddr_t)p4 % 0x100));
514 if (!r)
515 ret = -1;
516 LOG(" => test %s", r ? "ok" : "FAILED");
517 LOG("");
518 LOG("- nex_free p1, p3, p4");
519 nex_free(p1);
520 nex_free(p3);
521 nex_free(p4);
522 p1 = NULL;
523 p3 = NULL;
524 p4 = NULL;
525
526 /* test memalign with invalid alignments */
527 p3 = nex_memalign(100, 1024);
528 LOG("- p3 = nex_memalign(%d, 1024)", 100);
529 p4 = nex_memalign(0, 1024);
530 LOG("- p4 = nex_memalign(%d, 1024)", 0);
531 LOG(" p1=%p p2=%p p3=%p p4=%p",
532 (void *)p1, (void *)p2, (void *)p3, (void *)p4);
533 r = (!p3 && !p4);
534 if (!r)
535 ret = -1;
536 LOG(" => test %s", r ? "ok" : "FAILED");
537 LOG("");
538 LOG("- nex_free p3, p4");
539 nex_free(p3);
540 nex_free(p4);
541 p3 = NULL;
542 p4 = NULL;
543
544 /* test free(NULL) */
545 LOG("- nex_free NULL");
546 nex_free(NULL);
547 LOG("");
548 LOG("nex_malloc test done");
549
550 return ret;
551 }
552 #else /* CFG_NS_VIRTUALIZATION */
self_test_nex_malloc(void)553 static int self_test_nex_malloc(void)
554 {
555 return 0;
556 }
557 #endif
558
check_virt_to_phys(vaddr_t va,paddr_t exp_pa,enum teecore_memtypes m)559 static int check_virt_to_phys(vaddr_t va, paddr_t exp_pa,
560 enum teecore_memtypes m)
561 {
562 paddr_t pa = 0;
563 void *v = NULL;
564
565 pa = virt_to_phys((void *)va);
566 LOG("virt_to_phys(%#"PRIxVA") => %#"PRIxPA" (expect %#"PRIxPA")",
567 va, pa, exp_pa);
568 if (pa != exp_pa)
569 goto fail;
570
571 if (!exp_pa)
572 return 0;
573
574 v = phys_to_virt(pa, m, 1);
575 LOG("phys_to_virt(%#"PRIxPA") => %p (expect %#"PRIxVA")",
576 pa, v, va);
577 if ((vaddr_t)v != va)
578 goto fail;
579 return 0;
580
581 fail:
582 LOG("Fail");
583 return -1;
584 }
585
check_phys_to_virt(paddr_t pa,void * exp_va,enum teecore_memtypes m)586 static int check_phys_to_virt(paddr_t pa, void *exp_va,
587 enum teecore_memtypes m)
588 {
589 paddr_t new_pa = 0;
590 void *v = NULL;
591
592 v = phys_to_virt(pa, m, 1);
593 LOG("phys_to_virt(%#"PRIxPA") => %p (expect %p)",
594 pa, v, exp_va);
595 if (v != exp_va)
596 goto fail;
597
598 if (!exp_va)
599 return 0;
600
601 new_pa = virt_to_phys(v);
602 LOG("virt_to_phys(%p) => %#"PRIxPA" (expect %#"PRIxPA")",
603 v, new_pa, pa);
604 if (new_pa != pa)
605 goto fail;
606 return 0;
607
608 fail:
609 LOG("Fail");
610 return -1;
611 }
612
self_test_va2pa(void)613 static int self_test_va2pa(void)
614 {
615 void *ptr = self_test_va2pa;
616 int ret = 0;
617
618 if (IS_ENABLED(CFG_DYN_CONFIG) && VCORE_FREE_SZ) {
619 vaddr_t va_base = VCORE_FREE_PA;
620 paddr_t pa_base = 0;
621
622 pa_base = virt_to_phys((void *)va_base);
623 if (!pa_base) {
624 LOG("virt_to_phys(%#"PRIxVA") => 0 Fail!", va_base);
625 return -1;
626 }
627
628 /*
629 * boot_mem_release_unused() and
630 * boot_mem_release_tmp_alloc() has been called during
631 * boot.
632 *
633 * First pages of VCORE_FREE are expected to be allocated
634 * with boot_mem_alloc() while the end of VCORE_FREE should
635 * have been freed by the two mentioned release functions.
636 */
637 if (check_virt_to_phys(va_base, pa_base, MEM_AREA_TEE_RAM))
638 ret = -1;
639 if (check_virt_to_phys(va_base + 16, pa_base + 16,
640 MEM_AREA_TEE_RAM))
641 ret = -1;
642 if (check_virt_to_phys(va_base + VCORE_FREE_SZ -
643 SMALL_PAGE_SIZE, 0, MEM_AREA_TEE_RAM))
644 ret = -1;
645 if (check_virt_to_phys(va_base + VCORE_FREE_SZ - 16, 0,
646 MEM_AREA_TEE_RAM))
647 ret = -1;
648 }
649
650 if (!IS_ENABLED(CFG_WITH_PAGER) &&
651 check_phys_to_virt(virt_to_phys(ptr), ptr, MEM_AREA_TEE_RAM))
652 ret = -1;
653 if (check_phys_to_virt(virt_to_phys(ptr), NULL, MEM_AREA_IO_SEC))
654 ret = -1;
655 if (check_virt_to_phys(0, 0, MEM_AREA_TEE_RAM))
656 ret = -1;
657 if (check_phys_to_virt(0, NULL, MEM_AREA_TEE_RAM))
658 ret = -1;
659
660 return ret;
661 }
662
663 #ifdef CFG_CORE_SANITIZE_KADDRESS
664
665 #define ASAN_TEST_SUCCESS 1
666 #define ASAN_TEST_BUF_SIZE 15
667
668 static char asan_test_sgbuf[ASAN_TEST_BUF_SIZE];
669 char asan_test_gbuf[ASAN_TEST_BUF_SIZE];
670 static const char asan_test_sgbuf_ro[ASAN_TEST_BUF_SIZE + 1];
671
672 static jmp_buf asan_test_jmp;
673
674 struct asan_test_ctx {
675 char *pmalloc1;
676 char *pmalloc2[3];
677 char write_value;
678 void (*write_func)(char *buf, size_t pos, char value);
679 char (*read_func)(char *buf, size_t pos);
680 void *(*memcpy_func)(void *__restrict dst,
681 const void *__restrict src, size_t size);
682 void *(*memset_func)(void *buf, int val, size_t size);
683 };
684
asan_out_of_bounds_write(char * buf,size_t pos,char value)685 static void asan_out_of_bounds_write(char *buf, size_t pos,
686 char value)
687 {
688 buf[pos] = value;
689 }
690
asan_out_of_bounds_read(char * buf,size_t pos)691 static char asan_out_of_bounds_read(char *buf, size_t pos)
692 {
693 return buf[pos];
694 }
695
asan_out_of_bounds_memcpy(void * __restrict dst,const void * __restrict src,size_t size)696 static void *asan_out_of_bounds_memcpy(void *__restrict dst,
697 const void *__restrict src,
698 size_t size)
699 {
700 return memcpy(dst, src, size);
701 }
702
asan_out_of_bounds_memset(void * buf,int val,size_t size)703 static void *asan_out_of_bounds_memset(void *buf, int val, size_t size)
704 {
705 return memset(buf, val, size);
706 }
707
asan_panic_test(void)708 static void asan_panic_test(void)
709 {
710 longjmp(asan_test_jmp, ASAN_TEST_SUCCESS);
711 }
712
asan_test_cleanup(struct asan_test_ctx * ctx)713 static void asan_test_cleanup(struct asan_test_ctx *ctx)
714 {
715 unsigned int i = 0;
716
717 free(ctx->pmalloc1);
718
719 for (; i < ARRAY_SIZE(ctx->pmalloc2); i++)
720 free(ctx->pmalloc2[i]);
721 }
722
asan_call_test(struct asan_test_ctx * ctx,void (* test)(struct asan_test_ctx * ctx),const char __maybe_unused * desc)723 static int asan_call_test(struct asan_test_ctx *ctx,
724 void (*test)(struct asan_test_ctx *ctx),
725 const char __maybe_unused *desc)
726 {
727 int ret = 0;
728
729 ret = setjmp(asan_test_jmp);
730 if (ret == 0) {
731 test(ctx);
732 ret = -1;
733 } else if (ret == ASAN_TEST_SUCCESS) {
734 ret = 0;
735 } else {
736 panic("Unexpected setjmp return");
737 }
738 LOG(" => [asan] test %s: %s", desc, !ret ? "ok" : "FAILED");
739 return ret;
740 }
741
742 #ifndef CFG_DYN_CONFIG
asan_stack(struct asan_test_ctx * ctx)743 static void asan_stack(struct asan_test_ctx *ctx)
744 {
745 char buf[ASAN_TEST_BUF_SIZE] = {0};
746
747 ctx->write_func(buf, ASAN_TEST_BUF_SIZE, ctx->write_value);
748 }
749 #endif
750
asan_global_stat(struct asan_test_ctx * ctx)751 static void asan_global_stat(struct asan_test_ctx *ctx)
752 {
753 ctx->write_func(asan_test_sgbuf, ASAN_TEST_BUF_SIZE,
754 ctx->write_value);
755 }
756
asan_global_ro(struct asan_test_ctx * ctx)757 static void asan_global_ro(struct asan_test_ctx *ctx)
758 {
759 ctx->read_func((char *)asan_test_sgbuf_ro,
760 ASAN_TEST_BUF_SIZE + 1);
761 }
762
asan_global(struct asan_test_ctx * ctx)763 static void asan_global(struct asan_test_ctx *ctx)
764 {
765 ctx->write_func(asan_test_gbuf, ASAN_TEST_BUF_SIZE,
766 ctx->write_value);
767 }
768
asan_malloc(struct asan_test_ctx * ctx)769 static void asan_malloc(struct asan_test_ctx *ctx)
770 {
771 ctx->pmalloc1 = malloc(ASAN_TEST_BUF_SIZE);
772
773 if (ctx->pmalloc1)
774 ctx->write_func(ctx->pmalloc1, ASAN_TEST_BUF_SIZE,
775 ctx->write_value);
776 }
777
asan_malloc2(struct asan_test_ctx * ctx)778 static void asan_malloc2(struct asan_test_ctx *ctx)
779 {
780 unsigned int i = 0;
781 char *p = NULL;
782 size_t aligned_size = ROUNDUP(ASAN_TEST_BUF_SIZE, 8);
783
784 for (; i < ARRAY_SIZE(ctx->pmalloc2); i++) {
785 ctx->pmalloc2[i] = malloc(aligned_size);
786 if (!ctx->pmalloc2[i])
787 return;
788 }
789 p = ctx->pmalloc2[1];
790 ctx->write_func(p, aligned_size, ctx->write_value);
791 }
792
asan_use_after_free(struct asan_test_ctx * ctx)793 static void asan_use_after_free(struct asan_test_ctx *ctx)
794 {
795 char *a = malloc(ASAN_TEST_BUF_SIZE);
796
797 if (a) {
798 free(a);
799 ctx->write_func(a, 0, ctx->write_value);
800 }
801 }
802
asan_memcpy_dst(struct asan_test_ctx * ctx)803 static void asan_memcpy_dst(struct asan_test_ctx *ctx)
804 {
805 static char b[ASAN_TEST_BUF_SIZE + 1];
806 static char a[ASAN_TEST_BUF_SIZE];
807
808 ctx->memcpy_func(a, b, sizeof(b));
809 }
810
asan_memcpy_src(struct asan_test_ctx * ctx)811 static void asan_memcpy_src(struct asan_test_ctx *ctx)
812 {
813 static char b[ASAN_TEST_BUF_SIZE];
814 static char a[ASAN_TEST_BUF_SIZE + 1];
815
816 ctx->memcpy_func(a, b, sizeof(a));
817 }
818
asan_memset(struct asan_test_ctx * ctx)819 static void asan_memset(struct asan_test_ctx *ctx)
820 {
821 static char b[ASAN_TEST_BUF_SIZE];
822
823 ctx->memset_func(b, ctx->write_value, ASAN_TEST_BUF_SIZE + 1);
824 }
825
self_test_asan(void)826 static int self_test_asan(void)
827 {
828 uint32_t vfp_state = UINT32_C(0);
829 int ret = 0;
830 struct asan_test_ctx ctx = {0};
831
832 ctx.write_value = 0xab;
833 ctx.write_func = asan_out_of_bounds_write;
834 ctx.read_func = asan_out_of_bounds_read;
835 ctx.memcpy_func = asan_out_of_bounds_memcpy;
836 ctx.memset_func = asan_out_of_bounds_memset;
837
838 asan_set_panic_cb(asan_panic_test);
839 /*
840 * We need enable access to floating-point registers, in other
841 * way sync exception during setjmp/longjmp will occur.
842 */
843 vfp_state = thread_kernel_enable_vfp();
844
845 if (asan_call_test(&ctx, asan_global_stat, "(s) glob overflow") ||
846 asan_call_test(&ctx, asan_global, "glob overflow") ||
847 asan_call_test(&ctx, asan_global_ro, "glob ro overflow") ||
848 #ifndef CFG_DYN_CONFIG
849 asan_call_test(&ctx, asan_stack, "stack overflow") ||
850 #endif
851 asan_call_test(&ctx, asan_malloc, "malloc") ||
852 asan_call_test(&ctx, asan_malloc2, "malloc2") ||
853 asan_call_test(&ctx, asan_use_after_free, "use_after_free") ||
854 asan_call_test(&ctx, asan_memcpy_dst, "memcpy_dst") ||
855 asan_call_test(&ctx, asan_memcpy_src, "memcpy_src") ||
856 asan_call_test(&ctx, asan_memset, "memset")) {
857 ret = -1;
858 }
859
860 thread_kernel_disable_vfp(vfp_state);
861 asan_test_cleanup(&ctx);
862 asan_set_panic_cb(asan_panic);
863 return ret;
864 }
865 #else
self_test_asan(void)866 static int self_test_asan(void)
867 {
868 return 0;
869 }
870 #endif
871
872 /* exported entry points for some basic test */
core_self_tests(uint32_t nParamTypes __unused,TEE_Param pParams[TEE_NUM_PARAMS]__unused)873 TEE_Result core_self_tests(uint32_t nParamTypes __unused,
874 TEE_Param pParams[TEE_NUM_PARAMS] __unused)
875 {
876 if (self_test_mul_signed_overflow() || self_test_add_overflow() ||
877 self_test_sub_overflow() || self_test_mul_unsigned_overflow() ||
878 self_test_division() || self_test_malloc() ||
879 self_test_nex_malloc() || self_test_va2pa() ||
880 self_test_asan()) {
881 EMSG("some self_test_xxx failed! you should enable local LOG");
882 return TEE_ERROR_GENERIC;
883 }
884 return TEE_SUCCESS;
885 }
886
887 /* Exported entrypoint for dt_driver tests */
core_dt_driver_tests(uint32_t nParamTypes __unused,TEE_Param pParams[TEE_NUM_PARAMS]__unused)888 TEE_Result core_dt_driver_tests(uint32_t nParamTypes __unused,
889 TEE_Param pParams[TEE_NUM_PARAMS] __unused)
890 {
891 if (IS_ENABLED(CFG_DT_DRIVER_EMBEDDED_TEST)) {
892 if (dt_driver_test_status())
893 return TEE_ERROR_GENERIC;
894 } else {
895 IMSG("dt_driver tests are not embedded");
896 }
897
898 return TEE_SUCCESS;
899 }
900