blob: 8d218a858703b402e157cc417e7f98cd06caed2c [file] [log] [blame]
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001/*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6#include <CppUTest/CommandLineTestRunner.h>
7#include <CppUTest/TestHarness.h>
8
9extern "C" {
10#include <arch_helpers.h>
11#include <debug.h>
12#include <host_utils.h>
13#include <stdlib.h>
14#include <string.h>
15#include <test_helpers.h>
16#include <utils_def.h>
17#include <xlat_contexts.h> /* API to test */
18#include <xlat_defs.h>
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +010019#include <xlat_defs_private.h>
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +010020#include <xlat_tables.h> /* API to test */
21#include <xlat_test_defs.h>
22#include <xlat_test_helpers.h>
23}
24
25TEST_GROUP(xlat_tests_G2) {
26 TEST_SETUP()
27 {
28 test_helpers_init();
29 xlat_test_hepers_arch_init();
30 }
31
32 TEST_TEARDOWN()
33 {}
34};
35
36/*
37 * Generate VA space parameters given a walk start level and a region.
38 * The VA returned will fit in a single table of level `level`, so that
39 * there translation can start at that given level.
40 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +010041static uint64_t gen_va_space_params_by_lvl(int level,
42 xlat_addr_region_id_t region,
43 size_t *va_size)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +010044{
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +010045 assert(level >= XLAT_TEST_MIN_LVL());
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +010046 assert(level <= XLAT_TABLE_LEVEL_MAX);
47 assert(va_size != NULL);
48
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +010049 *va_size = (1ULL << XLAT_ADDR_SHIFT(level)) *
50 XLAT_GET_TABLE_ENTRIES(level);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +010051
52 return xlat_test_helpers_get_start_va(region, *va_size);
53}
54
55/*
56 * Generate a mmap array containing a set of mmap regions defined by
57 * 'start_va', 'last_lvl' and 'offset'. The mmap array will have
58 * three regions:
59 *
60 * - First region mapped at the beginning of a table whose final
61 * lookup level is 'last_lvl'. This region will be descendant of
62 * an entry at the beginning of a table at level 'first_lvl'.
63 * - Second region mapped at a random index of a table whose final
64 * lookup level is 'last_lvl'. This region will be descendant of
65 * an entry at a random index of a table at level 'first_lvl'.
66 * - Third region mapped at the end of a table whose final
67 * lookup level is 'last_lvl'. This region will be descendant of
68 * an entry at the final entry of a table at level 'first_lvl'.
69 *
70 * ┌──────────┐
71 * ┌───────────────┤ First │
72 * │ │ Region │
73 * │ ├──────────┤
74 * │ │ │
75 * │ │ │
76 * │ │ │
77 * │ │ │
78 * │ │ │
79 * │ │ │
80 * │ │ │
81 * ┌──────────────┐ │ │ │
82 * │ │ │ │ │
83 * │ First entry ├───────┘ │ │
84 * ├──────────────┤ │ │
85 * │ Second entry │ │ │
86 * │ (Reserved) │ └──────────┘
87 * │ │
88 * ├──────────────┤
89 * │ │ ┌──────────┐
90 * │ │ │ │
91 * │ │ │ │
92 * │ │ │ │
93 * ├──────────────┤ ├──────────┤
94 * │ Second │ │ Second │
95 * │ Region ├────────────────────────┤ Region │
96 * ├──────────────┤ ├──────────┤
97 * │ │ │ │
98 * │ │ │ │
99 * │ │ │ │
100 * │ │ │ │
101 * │ │ │ │
102 * │ │ │ │
103 * ├──────────────┤ └──────────┘
104 * │ │
105 * │ Third Region ├───────┐
106 * └──────────────┘ │ ┌─────────┐
107 * First Level │ │ │
108 * │ │ │
109 * │ │ │
110 * │ │ │
111 * │ │ │
112 * │ │ │
113 * │ │ │
114 * │ │ │
115 * │ │ │
116 * │ │ │
117 * │ │ │
118 * │ │ │
119 * │ │ │
120 * │ ├─────────┤
121 * └─────────────────┤ Third |
122 * | region │
123 * └─────────┘
124 * Last level
125 *
126 * For all the mmap regions, the granularity (returned in *granularity) is
127 * setup to the minimum granularity needed to map a block at level 'last_lvl'.
128 * The size of the mmap region is setup to the same as the granularity.
129 *
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100130 * This function caters for the reduced number of entries on the
131 * tables at level -1.
132 *
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100133 * This function also returns :
134 * - An array ('tbl_idxs') with the expected indexes mapping
135 * the regions at the last level table.
136 */
137static int gen_mmap_array_by_level(xlat_mmap_region *mmap,
138 unsigned int *tbl_idxs,
139 unsigned int mmap_size,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100140 int first_lvl,
141 int last_lvl,
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100142 size_t *granularity,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100143 uint64_t start_va,
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100144 bool allow_transient)
145{
146 uint64_t attrs;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100147 uint64_t mmap_start_va = start_va;
148 unsigned int max_table_entries = XLAT_GET_TABLE_ENTRIES(first_lvl);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100149
150 assert(mmap_size >= 3U);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100151 assert(last_lvl > XLAT_TEST_MIN_LVL());
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100152 assert(last_lvl <= XLAT_TABLE_LEVEL_MAX);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100153 assert(first_lvl >= XLAT_TEST_MIN_LVL());
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100154 assert(first_lvl <= last_lvl);
155 assert(mmap != NULL);
156 assert(tbl_idxs != NULL);
157 assert(granularity != NULL);
158
159 /* Generate a mapping at the beginning of the table */
160 tbl_idxs[0U] = 0U;
161
162 /*
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100163 * Generate a mapping in a random position of the table.
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100164 * The entry after the first one will always be left intentionally
165 * unused.
166 */
167 tbl_idxs[1U] = test_helpers_get_rand_in_range(2,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100168 (max_table_entries - 2));
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100169
170 /* Generate a mapping at the end of the table */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100171 tbl_idxs[2U] = max_table_entries - 1U;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100172
173 do {
174 attrs = xlat_test_helpers_rand_mmap_attrs();
175 } while ((attrs == MT_TRANSIENT) && (allow_transient == false));
176
177 *granularity = XLAT_BLOCK_SIZE(last_lvl);
178
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100179 for (unsigned int i = 0U; i < 3U; i++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100180 mmap[i].base_va = mmap_start_va;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100181 if (first_lvl < last_lvl) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100182 /*
183 * Add an offset to the mmap region base VA so that
184 * this region will be mapped to a TTE in the
185 * `first_lvl` table at the same index as specified
186 * in tbl_idxs[].
187 */
188 mmap[i].base_va += tbl_idxs[i] *
189 XLAT_BLOCK_SIZE(first_lvl);
190 }
191
192 mmap[i].base_va += (tbl_idxs[i] * (*granularity));
193
194 /*
195 * PA can be any address (as long as there are not overlaps,
196 * for which there is a specific test). For simplicity,
197 * create an identity mapping using the base_va for the PA.
198 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100199 mmap[i].base_pa = mmap[i].base_va & XLAT_TEST_GET_PA_MASK();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100200 mmap[i].size = *granularity;
201 mmap[i].attr = attrs;
202 mmap[i].granularity = *granularity;
203 }
204
205 return 0;
206}
207
208/*
209 * Given a context and a set of expected indexes and levels for the last walk,
210 * validate that the translation tables in the context are valid.
211 * Note that this function expects a valid and initialized context.
212 */
213static void validate_xlat_tables(xlat_ctx *ctx, unsigned int *expected_idxs,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100214 int expected_level)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100215{
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100216 uint64_t tte, tte_oa, attrs, upper_attrs, lower_attrs, type;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100217 uint64_t exp_upper_attrs, exp_lower_attrs;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100218 unsigned int index, granularity, addr_offset;
219 uint64_t test_va, pa, pa_mask;
220 int level, retval;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100221
222 assert(ctx != NULL);
223 assert(expected_idxs != NULL);
224
225 for (unsigned int i = 0U; i < ctx->cfg->mmap_regions; i++) {
226 granularity = ctx->cfg->mmap[i].granularity;
227 addr_offset = test_helpers_get_rand_in_range(0,
228 granularity - 1U);
229 test_va = ctx->cfg->base_va + ctx->cfg->mmap[i].base_va +
230 addr_offset;
231 pa = ctx->cfg->mmap[i].base_pa + addr_offset;
232
233 /* Perform a table walk */
234 retval = xlat_test_helpers_table_walk(ctx, test_va,
235 &tte, NULL, &level,
236 &index);
237
238 /* Return value */
239 CHECK_VERBOSE((retval == 0),
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100240 "Perform table walk for addr 0x%lx", test_va);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100241
242 /* Last table level */
243 CHECK_EQUAL(expected_level, level);
244
245 /* tte index on the page */
246 CHECK_EQUAL(expected_idxs[i], index);
247
248 /* Expected tte attributes */
249 retval = xlat_test_helpers_get_attrs_for_va(ctx, test_va,
250 &attrs);
251
252 /* Return value */
253 CHECK_EQUAL(0, retval);
254
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100255 exp_upper_attrs = EXTRACT(UPPER_ATTRS, attrs);
256 upper_attrs = EXTRACT(UPPER_ATTRS, tte);
257 exp_lower_attrs = EXTRACT(LOWER_ATTRS, attrs);
258 if (is_feat_lpa2_4k_present() == true) {
259 lower_attrs = EXTRACT(LOWER_ATTRS,
260 (tte & ~TTE_OA_BITS_50_51_MASK));
261 } else {
262 lower_attrs = EXTRACT(LOWER_ATTRS, tte);
263 }
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100264
265 /* Validate that the attributes are as expected */
266 CHECK_VERBOSE((exp_upper_attrs == upper_attrs),
267 "Validate Upper Attrs: Read 0x%lx - Expected 0x%lx",
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100268 upper_attrs, exp_upper_attrs);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100269
270 CHECK_VERBOSE((exp_lower_attrs == lower_attrs),
271 "Validate Lower Attrs: Read 0x%lx - Expected 0x%lx",
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100272 lower_attrs, exp_lower_attrs);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100273
274 /* Validate the PA */
275 pa_mask = (1ULL << XLAT_ADDR_SHIFT(level)) - 1ULL;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100276 tte_oa = xlat_get_oa_from_tte(tte);
277
278 CHECK_EQUAL(tte_oa, (pa & ~pa_mask));
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100279
280 /* Validate the descriptor type */
281 type = (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC :
282 BLOCK_DESC;
283 CHECK_EQUAL(type, (tte & DESC_MASK));
284 }
285}
286
287TEST(xlat_tests_G2, xlat_ctx_init_TC6)
288{
289 struct xlat_ctx ctx;
290 struct xlat_ctx_cfg cfg;
291 struct xlat_ctx_tbls tbls;
292 uint64_t start_va;
293 size_t va_size, granularity;
294 unsigned int mmap_count;
295 xlat_addr_region_id_t va_region;
296 int retval;
297 struct xlat_mmap_region init_mmap[3U];
298 unsigned int tbl_idx[3U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100299 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100300
301 /**********************************************************************
302 * TEST CASE 6:
303 *
304 * For each possible base level, create a set of mmap regions
305 * ranging from level 1 (lowest level at which a valid walk can
306 * finish) to XLAT_TABLE_LEVEL_MAX.
307 *
308 * For each possible (va_region, base_lvl, end_lvl) triplet for a
309 * base table there will be three mmap regions created:
310 *
311 * - First region mapped at the beginning of a table whose final
312 * lookup level is 'last_lvl'. This region will be descendant of
313 * an entry at the beginning of a 'base_lvl' table.
314 * - Second region mapped at a random index of a table whose final
315 * lookup level is 'last_lvl'. This region will be descendant of
316 * an entry at a random index of a 'base_lvl' table.
317 * - Third region mapped at the end of a table whose final
318 * lookup level is 'last_lvl'. This region will be descendant of
319 * an entry at the end of a 'base_lvl'.
320 *
321 * Then verify that the tables can be walked and that the levels,
322 * offsets and attributes on the ttes are as expected.
323 *
324 * This test validates that the xlat library is able to create
325 * tables starting on any valid initial lookup level and
326 * finishing on any valid level as well.
327 *********************************************************************/
328
329 mmap_count = 3U;
330
331 /* The first level that supports blocks is L1 */
332 for (end_lvl = 1U; end_lvl <= XLAT_TABLE_LEVEL_MAX; end_lvl++) {
333 for (int i = 0U; i < VA_REGIONS; i++) {
334 va_region = (xlat_addr_region_id_t)i;
335
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100336 for (base_lvl = XLAT_TEST_MIN_LVL();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100337 base_lvl <= end_lvl;
338 base_lvl++) {
339
340 start_va = gen_va_space_params_by_lvl(base_lvl,
341 va_region,
342 &va_size);
343
344 retval = gen_mmap_array_by_level(&init_mmap[0U],
345 &tbl_idx[0U],
346 mmap_count,
347 base_lvl,
348 end_lvl,
349 &granularity,
350 start_va,
351 false);
352 /*
353 * verify that the test setup is correct so far
354 */
355 CHECK_TRUE(retval == 0);
356
357 /* Clean the data structures */
358 memset((void *)&ctx, 0,
359 sizeof(struct xlat_ctx));
360 memset((void *)&cfg, 0,
361 sizeof(struct xlat_ctx_cfg));
362 memset((void *)&tbls, 0,
363 sizeof(struct xlat_ctx_tbls));
364
365 /* Initialize the test structure */
366 retval = xlat_ctx_cfg_init(&cfg, va_region,
367 &init_mmap[0U],
368 mmap_count, va_size);
369
370 /*
371 * verify that the test setup is correct so far
372 */
373 CHECK_TRUE(retval == 0);
374
375 /* Test xlat_ctx_init() */
376 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
377 xlat_test_helpers_tbls(),
378 XLAT_TESTS_MAX_TABLES);
379
380 /*
381 * verify that the test setup is correct so far
382 */
383 CHECK_TRUE(retval == 0);
384
385 validate_xlat_tables(&ctx, &tbl_idx[0U],
386 end_lvl);
387 }
388 }
389 }
390}
391
392TEST(xlat_tests_G2, xlat_get_llt_from_va_TC1)
393{
394 struct xlat_ctx ctx;
395 struct xlat_ctx_cfg cfg;
396 struct xlat_ctx_tbls tbls;
397 struct xlat_llt_info tbl_info, tbl_val;
398 struct xlat_mmap_region init_mmap[3U];
399 uint64_t start_va;
400 size_t va_size, granularity;
401 unsigned int mmap_count, index;
402 xlat_addr_region_id_t va_region;
403 int retval;
404 unsigned int tbl_idx[3U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100405 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100406 unsigned int mmap_idx;
407 uint64_t tte;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100408 uint64_t test_va;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100409
410 /***************************************************************
411 * TEST CASE 1:
412 *
413 * For each possible base level, create a set of mmap regions
414 * ranging from level 1 (lowest level at which a valid walk can
415 * finish) to XLAT_TABLE_LEVEL_MAX.
416 *
417 * For each possible (va_region, base_lvl, end_lvl) triplet,
418 * create 3 mappings that will correspond to a tte in the Last
419 * level Table. Then verify that the call to
420 * xlat_get_llt_from_va() is able to return the right
421 * xlat_tbl_info structure with the expected values.
422 ***************************************************************/
423
424 mmap_count = 3U;
425 va_region = (xlat_addr_region_id_t)test_helpers_get_rand_in_range(
426 0, VA_REGIONS - 1);
427
428 for (end_lvl = 1U;
429 end_lvl <= XLAT_TABLE_LEVEL_MAX;
430 end_lvl++) {
431
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100432 for (base_lvl = XLAT_TEST_MIN_LVL();
433 base_lvl <= end_lvl;
434 base_lvl++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100435
436 /* Clean the data structures */
437 memset((void *)&ctx, 0,
438 sizeof(struct xlat_ctx));
439 memset((void *)&cfg, 0,
440 sizeof(struct xlat_ctx_cfg));
441 memset((void *)&tbls, 0,
442 sizeof(struct xlat_ctx_tbls));
443 memset((void *)&tbl_info, 0,
444 sizeof(struct xlat_llt_info));
445 memset((void *)&tbl_val, 0,
446 sizeof(struct xlat_llt_info));
447
448 start_va = gen_va_space_params_by_lvl(base_lvl,
449 va_region,
450 &va_size);
451
452 /*
453 * Use gen_mmap_array_by_level() to generate
454 * the mmap array.
455 */
456 retval = gen_mmap_array_by_level(&init_mmap[0U],
457 &tbl_idx[0U],
458 mmap_count,
459 base_lvl,
460 end_lvl,
461 &granularity,
462 start_va,
463 true);
464
465 /* Ensure that so far the test setup is OK */
466 CHECK_TRUE(retval == 0);
467
468 retval = xlat_ctx_cfg_init(&cfg, va_region,
469 &init_mmap[0U],
470 mmap_count, va_size);
471
472 /* Ensure that so far the test setup is OK */
473 CHECK_TRUE(retval == 0);
474
475 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
476 xlat_test_helpers_tbls(),
477 XLAT_TESTS_MAX_TABLES);
478
479 /* Ensure that so far the test setup is OK */
480 CHECK_TRUE(retval == 0);
481
482 for (mmap_idx = 0U; mmap_idx < mmap_count; mmap_idx++) {
483 /*
484 * For each mmap region, pick up a
485 * random address for the test.
486 */
487 test_va = init_mmap[mmap_idx].base_va
488 + ctx.cfg->base_va;
489 test_va +=
490 test_helpers_get_rand_in_range(0,
491 init_mmap[mmap_idx].size - 1);
492
493 /*
494 * Perform a table walk to retrieve
495 * table info. Store the expected values
496 * inside the validation xlat_llt_info
497 * structure.
498 */
499 retval = xlat_test_helpers_table_walk(&ctx,
500 test_va,
501 &tte,
502 &(tbl_val.table),
503 &(tbl_val.level),
504 &index);
505
506 /*
507 * Calculate the expected base VA for the llt.
508 */
509 tbl_val.llt_base_va = start_va;
510 tbl_val.llt_base_va += (base_lvl < end_lvl) ?
511 (XLAT_BLOCK_SIZE(base_lvl) *
512 tbl_idx[mmap_idx]) : 0;
513
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100514 /* Ensure that so far the test setup is OK */
515 CHECK_TRUE(retval == 0);
516
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100517 VERBOSE("\nTesting VA 0x%lx", test_va);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100518
519 /* Test xlat_get_llt_from_va */
520 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
521 test_va);
522
523 /* Check the return value */
524 CHECK_TRUE(retval == 0);
525
526 /*
527 * Validate the structure returned by
528 * xlat_get_llt_from_va
529 */
530 MEMCMP_EQUAL((void *)&tbl_val,
531 (void *)&tbl_info,
532 sizeof(struct xlat_llt_info));
533 VERBOSE(" : PASS\n\n");
534 }
535 }
536 }
537}
538
539TEST(xlat_tests_G2, xlat_get_llt_from_va_TC2)
540{
541 struct xlat_ctx ctx;
542 struct xlat_ctx_cfg cfg;
543 struct xlat_ctx_tbls tbls;
544 struct xlat_llt_info tbl_info;
545 struct xlat_mmap_region init_mmap[3U];
546 unsigned int tbl_idx[3U];
547 size_t va_size, granularity;
548 uint64_t start_va, test_va;
549 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100550 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100551 int retval;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100552 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100553
554 /***************************************************************
555 * TEST CASE 2:
556 *
557 * Test xlat_get_llt_from_va() with a VAs ouside
558 * of the context VA space.
559 ***************************************************************/
560
561 /*
562 * Pick up a base and end levels for the translation tables.
563 * The leves are arbitrary. Just to have a VA space enough
564 * for the tests.
565 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100566 base_lvl = 2;
567 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100568
569 for (int i = 0U; i < VA_REGIONS; i++) {
570 va_region = (xlat_addr_region_id_t)i;
571
572 /*
573 * For the low region, the test will be executed
574 * only once, for a VA above the VA space limits.
575 *
576 * For the high region, the test will be executed twice:
577 * - Once for VA below the VA space.
578 * - Once of a VA above the VA space.
579 */
580 for (unsigned int j = 0; j < (i + 1U); j++) {
581
582 /* Clean the data structures */
583 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
584 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
585 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
586 memset((void *)&tbl_info, 0,
587 sizeof(struct xlat_llt_info));
588
589 /* Get VA space limits for Level 2 */
590 start_va = gen_va_space_params_by_lvl(base_lvl, va_region,
591 &va_size);
592
593 /*
594 * use gen_mmap_array_by_level() to generate
595 * the mmap for convenience.
596 */
597 retval = gen_mmap_array_by_level(&init_mmap[0U],
598 &tbl_idx[0U],
599 3U, base_lvl, end_lvl,
600 &granularity,
601 start_va,
602 true);
603
604 /* Ensure that so far the test setup is OK */
605 CHECK_TRUE(retval == 0);
606
607 retval = xlat_ctx_cfg_init(&cfg, va_region,
608 &init_mmap[0U], 3U,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100609 max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100610 CHECK_TRUE(retval == 0);
611
612 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
613 xlat_test_helpers_tbls(),
614 XLAT_TESTS_MAX_TABLES);
615 CHECK_TRUE(retval == 0);
616
617 VERBOSE("\n");
618
619 if (j == 0U) {
620 /*
621 * VA above the VA space.
622 * The upper range of the address is arbitrary.
623 */
624 test_va = (ctx.cfg->max_va_size) +
625 test_helpers_get_rand_in_range(0,
626 XLAT_BLOCK_SIZE(base_lvl) - 1);
627 } else {
628 /*
629 * VA below the VA space.
630 * The upper range of the address is arbitrary.
631 */
632 test_va = test_helpers_get_rand_in_range(0,
633 XLAT_BLOCK_SIZE(base_lvl) - 1);
634 }
635
636 /* Test xlat_get_llt_from_va */
637 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
638
639 /* Check the return value */
640 CHECK_VERBOSE((retval == -EFAULT),
641 "Testing VA 0x%lx", test_va);
642 VERBOSE("\n");
643 }
644 }
645}
646
647TEST(xlat_tests_G2, xlat_get_llt_from_va_TC3)
648{
649 struct xlat_ctx ctx;
650 struct xlat_ctx_cfg cfg;
651 struct xlat_ctx_tbls tbls;
652 struct xlat_llt_info tbl_info;
653 struct xlat_mmap_region init_mmap[3U];
654 unsigned int tbl_idx[3U];
655 size_t va_size, granularity;
656 uint64_t start_va, test_va;
657 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100658 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100659 int retval;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100660 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100661
662 /***************************************************************
663 * TEST CASE 3:
664 *
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100665 * Test xlat_get_llt_from_va() with an unmapped VA belonging to
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100666 * the context VA space.
667 ***************************************************************/
668
669 /*
670 * Pick up a base and end levels for the translation tables.
671 * The leves are arbitrary. Just to have a VA space enough
672 * for the tests.
673 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100674 base_lvl = XLAT_TEST_MIN_LVL();
675 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100676
677 for (int i = 0U; i < VA_REGIONS; i++) {
678 va_region = (xlat_addr_region_id_t)i;
679
680 /* Clean the data structures */
681 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
682 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
683 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
684 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
685
686 /* VA space boundaries */
687 start_va = gen_va_space_params_by_lvl(base_lvl, va_region,
688 &va_size);
689
690 /*
691 * use gen_mmap_array_by_level() to generate
692 * the mmap for convenience, although we will
693 * only use one of the mmap regions (init_mmap[0]).
694 */
695 retval = gen_mmap_array_by_level(&init_mmap[0U],
696 &tbl_idx[0U],
697 3U, base_lvl, end_lvl,
698 &granularity,
699 start_va,
700 true);
701
702 /* Ensure that so far the test setup is OK */
703 CHECK_TRUE(retval == 0);
704
705 retval = xlat_ctx_cfg_init(&cfg, va_region,
706 &init_mmap[0U], 3U,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100707 max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100708 CHECK_TRUE(retval == 0);
709
710 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
711 xlat_test_helpers_tbls(),
712 XLAT_TESTS_MAX_TABLES);
713 CHECK_TRUE(retval == 0);
714
715 VERBOSE("\n");
716
717 test_va = ctx.cfg->base_va;
718 test_va += (init_mmap[0U].base_va + init_mmap[0U].size);
719 test_va += test_helpers_get_rand_in_range(1, PAGE_SIZE - 1);
720
721 /* Test xlat_get_llt_from_va */
722 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
723
724 /* Check the return value */
725 CHECK_VERBOSE((retval == 0),
726 "Testing VA 0x%lx", test_va);
727 VERBOSE("\n");
728 }
729}
730
731void xlat_get_llt_from_va_prepare_assertion(struct xlat_ctx *ctx,
732 struct xlat_ctx_cfg *cfg,
733 struct xlat_ctx_tbls *tbls,
734 struct xlat_mmap_region *init_mmap)
735{
736 uint64_t start_va, end_va;
737 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100738 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100739
740 assert(ctx != NULL);
741 assert(cfg != NULL);
742 assert(tbls != NULL);
743 assert(init_mmap != NULL);
744
745 va_region = (xlat_addr_region_id_t)test_helpers_get_rand_in_range(0,
746 VA_REGIONS - 1U);
747
748 /* Clean the data structures */
749 memset((void *)ctx, 0, sizeof(struct xlat_ctx));
750 memset((void *)cfg, 0, sizeof(struct xlat_ctx_cfg));
751 memset((void *)tbls, 0, sizeof(struct xlat_ctx_tbls));
752
753 /* VA space boundaries */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100754 start_va = xlat_test_helpers_get_start_va(va_region, max_va_size);
755 end_va = start_va + max_va_size - 1ULL;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100756
757 /* Generate a random mmap area */
758 xlat_test_helpers_rand_mmap_array(init_mmap, 1U, start_va, end_va);
759
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100760 (void)xlat_ctx_cfg_init(cfg, va_region, init_mmap, 1U, max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100761
762 (void)xlat_ctx_init(ctx, cfg, tbls,
763 xlat_test_helpers_tbls(),
764 XLAT_TESTS_MAX_TABLES);
765}
766
767ASSERT_TEST(xlat_tests_G2, xlat_get_llt_from_va_TC4)
768{
769
770 struct xlat_ctx ctx;
771 struct xlat_ctx_cfg cfg;
772 struct xlat_ctx_tbls tbls;
773 struct xlat_mmap_region init_mmap;
774 uint64_t test_va;
775
776 /***************************************************************
777 * TEST CASE 4:
778 *
779 * Try calling xlat_get_llt_from_va() with a NULL
780 * xlat_llt_info structure
781 ***************************************************************/
782
783 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
784
785 test_va = ctx.cfg->base_va + init_mmap.base_va;
786
787 /* Test xlat_get_llt_from_va */
788 test_helpers_expect_assert_fail(true);
789 (void)xlat_get_llt_from_va(NULL, &ctx, test_va);
790 test_helpers_fail_if_no_assert_failed();
791}
792
793ASSERT_TEST(xlat_tests_G2, xlat_get_llt_from_va_TC5)
794{
795 struct xlat_llt_info tbl_info;
796
797 /***************************************************************
798 * TEST CASE 5:
799 *
800 * Try calling xlat_get_llt_from_va() with a NULL
801 * xlat_ctx structure.
802 ***************************************************************/
803
804 /* Clean the data structures */
805 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
806
807 /* Test xlat_get_llt_from_va: NULL xlat_ctx */
808 test_helpers_expect_assert_fail(true);
809 (void)xlat_get_llt_from_va(&tbl_info, NULL, 0ULL);
810 test_helpers_fail_if_no_assert_failed();
811}
812
813ASSERT_TEST(xlat_tests_G2, xlat_get_llt_from_va_TC6)
814{
815 struct xlat_ctx ctx;
816 struct xlat_ctx_cfg cfg;
817 struct xlat_ctx_tbls tbls;
818 struct xlat_llt_info tbl_info;
819 struct xlat_mmap_region init_mmap;
820 uint64_t test_va;
821
822 /***************************************************************
823 * TEST CASE 6:
824 *
825 * Try calling xlat_get_llt_from_va() with a NULL
826 * xlat_ctx_cfg structure.
827 ***************************************************************/
828
829 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
830 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
831
832 test_va = ctx.cfg->base_va + init_mmap.base_va;
833
834 /* Test xlat_get_llt_from_va: NULL xlat_ctx.cfg */
835 ctx.cfg = NULL;
836 test_helpers_expect_assert_fail(true);
837 (void)xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
838 test_helpers_fail_if_no_assert_failed();
839}
840
841ASSERT_TEST(xlat_tests_G2, xlat_get_llt_from_va_TC7)
842{
843 struct xlat_ctx ctx;
844 struct xlat_ctx_cfg cfg;
845 struct xlat_ctx_tbls tbls;
846 struct xlat_llt_info tbl_info;
847 struct xlat_mmap_region init_mmap;
848 uint64_t test_va;
849
850 /***************************************************************
851 * TEST CASE 7:
852 *
853 * Try calling xlat_get_llt_from_va() with a NULL
854 * xlat_ctx_tbls structure.
855 ***************************************************************/
856
857 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
858 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
859
860 test_va = ctx.cfg->base_va + init_mmap.base_va;
861
862 /* Test xlat_get_llt_from_va: NULL xlat_ctx.tbls */
863 ctx.tbls = NULL;
864 test_helpers_expect_assert_fail(true);
865 (void)xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
866 test_helpers_fail_if_no_assert_failed();
867}
868
869ASSERT_TEST(xlat_tests_G2, xlat_get_llt_from_va_TC8)
870{
871 struct xlat_ctx ctx;
872 struct xlat_ctx_cfg cfg;
873 struct xlat_ctx_tbls tbls;
874 struct xlat_llt_info tbl_info;
875 struct xlat_mmap_region init_mmap;
876 uint64_t test_va;
877
878 /***************************************************************
879 * TEST CASE 8:
880 *
881 * Try calling xlat_get_llt_from_va() with an uninitialized
882 * xlat_ctx_cfg structure.
883 * Perform a full initialization of the context and then force
884 * 'ctx.cfg->initialized' to 'false' so we can ensure that
885 * this is what it is actually tested.
886 ***************************************************************/
887
888 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
889 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
890
891 test_va = ctx.cfg->base_va + init_mmap.base_va;
892
893 /* Mark the cfg structure as not initialized */
894 cfg.initialized = false;
895
896 test_helpers_expect_assert_fail(true);
897 (void)xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
898 test_helpers_fail_if_no_assert_failed();
899}
900
901ASSERT_TEST(xlat_tests_G2, xlat_get_llt_from_va_TC9)
902{
903 struct xlat_ctx ctx;
904 struct xlat_ctx_cfg cfg;
905 struct xlat_ctx_tbls tbls;
906 struct xlat_llt_info tbl_info;
907 struct xlat_mmap_region init_mmap;
908 uint64_t test_va;
909
910 /***************************************************************
911 * TEST CASE 9:
912 *
913 * Try calling xlat_get_llt_from_va() with an uninitialized
914 * xlat_ctx_tbls structure.
915 * Perform a full initialization of the context and then force
916 * 'ctx.tbls->initialized' to 'false' so we can ensure that
917 * this is what it is actually tested.
918 ***************************************************************/
919
920 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
921 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
922
923 test_va = ctx.cfg->base_va + init_mmap.base_va;
924
925 /* Mark the tbls structure as not initialized */
926 tbls.initialized = false;
927
928 test_helpers_expect_assert_fail(true);
929 (void)xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
930 test_helpers_fail_if_no_assert_failed();
931}
932
933TEST(xlat_tests_G2, xlat_get_tte_ptr_TC1)
934{
935 struct xlat_ctx ctx;
936 struct xlat_ctx_cfg cfg;
937 struct xlat_ctx_tbls tbls;
938 struct xlat_llt_info tbl_info;
939 struct xlat_mmap_region init_mmap[3U];
940 unsigned int tbl_idx[3U];
941 uint64_t start_va, test_va;
942 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100943 unsigned int index;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100944 uint64_t *tte_ptr, *val_tte, *table;
945 uint64_t tte;
946 size_t granularity;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100947 int base_lvl, end_lvl;
948 int level, retval;
949 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100950
951 /***************************************************************
952 * TEST CASE 1:
953 *
954 * Initialize a translation context with a given VA space and
955 * 3 mmap regions at level 3. Then get a tte using
956 * xlat_get_tte_ptr() and verify that it is the correct entry.
957 *
958 * This test tries three different mmap areas per VA region:
959 *
Soby Mathewbddaba12023-04-22 03:34:00 +0000960 * - An address corresponding to the first entry at a
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100961 * last level table.
962 * - An address corresponding to the last entry at a
963 * last level table.
964 * - An address corresponding to an intermediate entry
965 * at a last level table.
966 *
Soby Mathewbddaba12023-04-22 03:34:00 +0000967 * The test also tests 2 negative cases :
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100968 * 1. It tries to get the TTE via xlat_get_tte() for a lower
969 * VA than the base VA.
970 * 2. It tries to get the TTE for a higher VA than is mapped
971 * by the last level table.
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100972 ***************************************************************/
973
974 /*
975 * Pick up a base and end levels for the translation tables.
976 * The leves are arbitrary. Just to have a VA space enough
977 * for the tests.
978 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100979 base_lvl = XLAT_TEST_MIN_LVL();
980 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100981
982 for (int i = 0U; i < VA_REGIONS; i++) {
983 va_region = (xlat_addr_region_id_t)i;
984
985 /* Clean the data structures */
986 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
987 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
988 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
989 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
990
991 /* VA space boundaries */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100992 start_va = xlat_test_helpers_get_start_va(va_region, max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100993
994 /* Generate the mmap regions */
995 retval = gen_mmap_array_by_level(&init_mmap[0U],
996 &tbl_idx[0U],
997 3U, base_lvl, end_lvl,
998 &granularity,
999 start_va, true);
1000
1001 /* Ensure that so far the test setup is OK */
1002 CHECK_TRUE(retval == 0);
1003
1004 retval = xlat_ctx_cfg_init(&cfg, va_region, &init_mmap[0U], 3U,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001005 max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001006
1007 /* Ensure that so far the test setup is OK */
1008 CHECK_TRUE(retval == 0);
1009
1010 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1011 xlat_test_helpers_tbls(),
1012 XLAT_TESTS_MAX_TABLES);
1013
1014 /* Ensure that so far the test setup is OK */
1015 CHECK_TRUE(retval == 0);
1016
1017 /* Get the xlat_llt_info structure used to look for TTEs */
1018 test_va = ctx.cfg->base_va + init_mmap[0].base_va;
1019 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1020
1021 /* Ensure that so far the test setup is OK */
1022 CHECK_TRUE(retval == 0);
1023
1024 /*
1025 * Iterate over test VAs of all 3 mmap regions to
1026 * test xlat_get_tte_ptr().
1027 */
1028 VERBOSE("\n");
1029 for (unsigned int i = 0U; i < 3U; i++) {
1030 /*
1031 * Get the xlat_llt_info structure used
1032 * to look for TTEs.
1033 */
1034 test_va = ctx.cfg->base_va + init_mmap[i].base_va;
1035 retval = xlat_get_llt_from_va(&tbl_info,
1036 &ctx, test_va);
1037
1038 /* Ensure that so far the test setup is OK */
1039 CHECK_TRUE(retval == 0);
1040
1041 /*
1042 * Add a random offset to the current 'test_va'
1043 * to be used for the tests.
1044 */
1045 test_va += test_helpers_get_rand_in_range(0,
1046 PAGE_SIZE - 1);
1047
1048 /*
1049 * Perform a table walk to get the table containing
1050 * the tte we are insterested in as well as the
1051 * index of that tte in the table.
1052 */
1053 retval = xlat_test_helpers_table_walk(&ctx, test_va,
1054 &tte, &table,
1055 &level, &index);
1056 /* Ensure that so far the test setup is OK */
1057 CHECK_TRUE(retval == 0);
1058
1059 /* Get a pointer to the expected tte */
1060 val_tte = &table[index];
1061
1062 /* Test xlat_get_tte_ptr() */
1063 tte_ptr = xlat_get_tte_ptr(&tbl_info, test_va);
1064
1065 /* Validate the output */
1066 CHECK_VERBOSE((val_tte == tte_ptr),
1067 "Testing VA 0x%lx", test_va);
1068 }
1069
1070 /*
1071 * test xlat_get_tte_ptr() agains a VA below the minimum
1072 * VA mapped by 'tbl_info'. Use init_mmap[1] for this test.
1073 */
1074 test_va = ctx.cfg->base_va + init_mmap[1U].base_va;
1075 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1076
1077 /* Ensure that so far the test setup is OK */
1078 CHECK_TRUE(retval == 0);
1079
1080 test_va = tbl_info.llt_base_va;
1081 test_va -= test_helpers_get_rand_in_range(1, PAGE_SIZE - 1);
1082
1083 tte_ptr = xlat_get_tte_ptr(&tbl_info, test_va);
1084
1085
1086 /* Validate the output */
1087 CHECK_VERBOSE((tte_ptr == NULL),
1088 "Check address 0x%lx against TT at VA 0x%lx",
1089 test_va, tbl_info.llt_base_va);
1090
Soby Mathewbddaba12023-04-22 03:34:00 +00001091 /*
1092 * test xlat_get_tte_ptr() against a VA above the max
1093 * VA mapped by 'tbl_info'. Use init_mmap[0] for this test.
1094 */
1095 test_va = ctx.cfg->base_va + init_mmap[0U].base_va;
1096 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1097
1098 /* Ensure that so far the test setup is OK */
1099 CHECK_TRUE(retval == 0);
1100
1101 test_va = tbl_info.llt_base_va + XLAT_BLOCK_SIZE(tbl_info.level - 1);
1102 test_va += test_helpers_get_rand_in_range(1, PAGE_SIZE - 1);
1103
1104 tte_ptr = xlat_get_tte_ptr(&tbl_info, test_va);
1105
1106 /* Validate the output */
1107 CHECK_VERBOSE((tte_ptr == NULL),
1108 "Check address 0x%lx against TT at VA 0x%lx",
1109 test_va, tbl_info.llt_base_va);
1110
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001111 VERBOSE("\n");
1112 }
1113}
1114
1115ASSERT_TEST(xlat_tests_G2, xlat_get_tte_ptr_TC2)
1116{
1117 /***************************************************************
1118 * TEST CASE 2:
1119 *
1120 * Try to get a tte using xlat_get_tte() with a NULL
1121 * xlat_llt_info structure.
1122 ***************************************************************/
1123
1124 test_helpers_expect_assert_fail(true);
1125 (void)xlat_get_tte_ptr(NULL, 0ULL);
1126 test_helpers_fail_if_no_assert_failed();
1127}
1128
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001129ASSERT_TEST(xlat_tests_G2, xlat_get_tte_ptr_TC3)
1130{
1131 struct xlat_ctx ctx;
1132 struct xlat_ctx_cfg cfg;
1133 struct xlat_ctx_tbls tbls;
1134 struct xlat_llt_info tbl_info;
1135 struct xlat_mmap_region init_mmap;
1136 uint64_t test_va;
1137
1138 /***************************************************************
1139 * TEST CASE 3:
1140 *
1141 * Try to get a tte using xlat_get_tte() in which 'level' is
1142 * below the minimum for the current architecture implementation.
1143 ***************************************************************/
1144
1145 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
1146 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
1147
1148 test_va = ctx.cfg->base_va + init_mmap.base_va;
1149
1150 /* Override the xlat_llt_info structure's level field */
1151 tbl_info.level = XLAT_TABLE_LEVEL_MIN - 1;
1152
1153 test_helpers_expect_assert_fail(true);
1154 (void)xlat_get_tte_ptr(&tbl_info, test_va);
1155 test_helpers_fail_if_no_assert_failed();
1156}
1157
1158ASSERT_TEST(xlat_tests_G2, xlat_get_tte_ptr_TC4)
1159{
1160 struct xlat_ctx ctx;
1161 struct xlat_ctx_cfg cfg;
1162 struct xlat_ctx_tbls tbls;
1163 struct xlat_llt_info tbl_info;
1164 struct xlat_mmap_region init_mmap;
1165 uint64_t test_va;
1166
1167 /***************************************************************
1168 * TEST CASE 4:
1169 *
1170 * Try to get a tte using xlat_get_tte() in which 'level' is
1171 * above the maximum for the current architecture implementation.
1172 ***************************************************************/
1173
1174 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
1175 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
1176
1177 test_va = ctx.cfg->base_va + init_mmap.base_va;
1178
1179 /* Override the xlat_llt_info structure's level field */
1180 tbl_info.level = XLAT_TABLE_LEVEL_MAX + 1;
1181
1182 test_helpers_expect_assert_fail(true);
1183 (void)xlat_get_tte_ptr(&tbl_info, test_va);
1184 test_helpers_fail_if_no_assert_failed();
1185}
1186
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001187TEST(xlat_tests_G2, xlat_unmap_memory_page_TC1)
1188{
1189 struct xlat_ctx ctx;
1190 struct xlat_ctx_cfg cfg;
1191 struct xlat_ctx_tbls tbls;
1192 uint64_t start_va;
1193 size_t va_size, granularity;
1194 unsigned int mmap_count;
1195 xlat_addr_region_id_t va_region;
1196 int retval;
1197 struct xlat_mmap_region init_mmap[3U];
1198 unsigned int tbl_idx[3U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001199 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001200
1201 /***************************************************************
1202 * TEST CASE 1:
1203 *
1204 * For each possible end lookup level, create a set transient
1205 * valid random mappings.
1206 *
1207 * For each possible (va_region, end_lvl) tuple, there will be
1208 * three mmap regions created:
1209 *
1210 * - First region mapped at the beginning of a table whose
1211 * final lookup level is 'end_lvl'
1212 * - Second region mapped at a random tte of a table whose
1213 * final lookup level is 'end_lvl'
1214 * - Third region mapped at the end of a table whose
1215 * final lookup level is 'end_lvl'
1216 *
1217 * Then verify that the tables can be unmapped and that the
1218 * resulting tte will contain a transient invalid entry.
1219 ***************************************************************/
1220
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001221 mmap_count = 3;
1222 base_lvl = XLAT_TEST_MIN_LVL();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001223
1224 /* The first look-up level that supports blocks is L1 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001225 for (end_lvl = 1; end_lvl <= XLAT_TABLE_LEVEL_MAX; end_lvl++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001226 for (int i = 0U; i < VA_REGIONS; i++) {
1227 va_region = (xlat_addr_region_id_t)i;
1228
1229 start_va = gen_va_space_params_by_lvl(base_lvl,
1230 va_region,
1231 &va_size);
1232
1233 retval = gen_mmap_array_by_level(&init_mmap[0U],
1234 &tbl_idx[0U],
1235 mmap_count,
1236 base_lvl,
1237 end_lvl,
1238 &granularity,
1239 start_va,
1240 false);
1241
1242 /* Verify that the test setup is correct so far */
1243 CHECK_TRUE(retval == 0);
1244
1245 /* Clean the data structures */
1246 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1247 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1248 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1249
1250 /* Initialize the test structure */
1251 retval = xlat_ctx_cfg_init(&cfg, va_region,
1252 &init_mmap[0U],
1253 mmap_count, va_size);
1254
1255 /* Verify that the test setup is correct so far */
1256 CHECK_TRUE(retval == 0);
1257
1258 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1259 xlat_test_helpers_tbls(),
1260 XLAT_TESTS_MAX_TABLES);
1261
1262 /* Verify that the test setup is correct so far */
1263 CHECK_TRUE(retval == 0);
1264
1265 /*
1266 * For each one of the mmap regions:
1267 * - get the TTE of a random VA and make it transient
1268 * - call xlat_unmap_memory_page() over the same VA
1269 * - verify that the TTE is now transient invalid.
1270 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001271 for (unsigned int j = 0U; j < mmap_count; j++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001272 uint64_t tte;
1273 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001274 unsigned int tte_idx;
1275 int tte_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001276 struct xlat_llt_info tbl_info;
1277 uint64_t offset =
1278 test_helpers_get_rand_in_range(0,
1279 PAGE_SIZE - 1);
1280 uint64_t test_va = init_mmap[j].base_va +
1281 ctx.cfg->base_va + offset;
1282
1283 /*
1284 * Perform a table walk to retrieve the table
1285 * where the VA is mapped along with the index
1286 * of the TTE within the table.
1287 */
1288 retval = xlat_test_helpers_table_walk(&ctx,
1289 test_va, &tte,
1290 &tbl_ptr, &tte_lvl,
1291 &tte_idx);
1292
1293 /*
1294 * Verify that the test setup is correct so far
1295 */
1296 CHECK_TRUE(retval == 0);
1297
1298 /*
1299 * The TTE is expected to be valid. Make it
1300 * transient valid within the table.
1301 */
1302 tbl_ptr[tte_idx] |=
1303 (1ULL << TRANSIENT_FLAG_SHIFT);
1304
1305 /*
1306 * Retrieve the xlat_llt_info structure needed
1307 * to feed xlat_unmap_memory_page()
1308 */
1309 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
1310 test_va);
1311
1312 /*
1313 * Verify that the test setup is correct so far
1314 */
1315 CHECK_TRUE(retval == 0);
1316
1317 /*
1318 * Try to unmap the page/block
1319 * containing `test_va`
1320 */
1321 retval = xlat_unmap_memory_page(&tbl_info,
1322 test_va);
1323
1324 /* Verify that the return is as expected */
1325 CHECK_TRUE(retval == 0);
1326
1327 /*
1328 * Verify that the TTE is marked as transient
1329 * invalid.
1330 */
1331 CHECK_VERBOSE((tbl_ptr[tte_idx] ==
1332 TRANSIENT_DESC),
1333 "Verifying TTE for VA 0x%lx is marked as Transient Invalid",
1334 test_va);
1335 }
1336 VERBOSE("\n");
1337 }
1338 }
1339}
1340
1341TEST(xlat_tests_G2, xlat_unmap_memory_page_TC2)
1342{
1343 struct xlat_ctx ctx;
1344 struct xlat_ctx_cfg cfg;
1345 struct xlat_ctx_tbls tbls;
1346 uint64_t start_va, test_va;
1347 size_t va_size, granularity;
1348 unsigned int mmap_count;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001349 unsigned int tte_idx;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001350 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001351 int retval, tte_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001352 struct xlat_mmap_region init_mmap[3U];
1353 unsigned int tbl_idx[3U];
1354 struct xlat_llt_info tbl_info;
1355 uint64_t tte, val_tte;
1356 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001357 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001358
1359 /***************************************************************
1360 * TEST CASE 2:
1361 *
1362 * Generate a mmap region with a set of transient valid
1363 * mappings. Then run a set of negative tests:
1364 *
1365 * - Try addresses below and above the range mapped by the
1366 * xlat_llt_info structure on a transient-valid entry.
1367 * - Try unmapping from a valid non-transient entry.
1368 * - Try unmapping from an invalid entry.
1369 ***************************************************************/
1370
1371 /*
1372 * Pick up a base and end levels for the translation tables.
1373 * The leves are arbitrary. Just to have a VA space enough
1374 * for the tests.
1375 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001376 base_lvl = XLAT_TEST_MIN_LVL();
1377 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001378
1379 mmap_count = 3U;
1380
1381 for (int i = 0U; i < VA_REGIONS; i++) {
1382 va_region = (xlat_addr_region_id_t)i;
1383
1384 start_va = gen_va_space_params_by_lvl(base_lvl,
1385 va_region, &va_size);
1386
1387 /*
1388 * We generate the mmap regions to use. We will be interested
1389 * in init_mmap[1].
1390 */
1391 retval = gen_mmap_array_by_level(&init_mmap[0U], &tbl_idx[0U],
1392 mmap_count, base_lvl, end_lvl,
1393 &granularity,
1394 start_va, false);
1395
1396 /* Verify that the test setup is correct so far */
1397 CHECK_TRUE(retval == 0);
1398
1399 /* Clean the data structures */
1400 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1401 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1402 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1403
1404 /* Initialize the test structure */
1405 retval = xlat_ctx_cfg_init(&cfg, va_region, &init_mmap[0U],
1406 mmap_count, va_size);
1407
1408 /* Verify that the test setup is correct so far */
1409 CHECK_TRUE(retval == 0);
1410
1411 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1412 xlat_test_helpers_tbls(),
1413 XLAT_TESTS_MAX_TABLES);
1414
1415 /* Verify that the test setup is correct so far */
1416 CHECK_TRUE(retval == 0);
1417
1418 /*
1419 * Make the TTEs of the mapped region, which is expected
1420 * to be valid, transient valid.
1421 */
1422 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1423
1424 /*
1425 * Perform a table walk to retrieve the table where the VA
1426 * is mapped along with the index of the TTE within the table.
1427 */
1428 retval = xlat_test_helpers_table_walk(&ctx, test_va, &tte,
1429 &tbl_ptr, &tte_lvl,
1430 &tte_idx);
1431
1432 /* Verify that the test setup is correct so far */
1433 CHECK_TRUE(retval == 0);
1434
1435 /*
1436 * The TTE is expected to be valid. Make it
1437 * transient valid within the table.
1438 */
1439 tbl_ptr[tte_idx] |= (1ULL << TRANSIENT_FLAG_SHIFT);
1440 val_tte = tbl_ptr[tte_idx];
1441
1442 /*
1443 * Retrieve the xlat_llt_info structure needed to feed
1444 * xlat_unmap_memory_page().
1445 */
1446 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
1447 init_mmap[1U].base_pa + ctx.cfg->base_va);
1448
1449 /* Verify that the test setup is correct so far */
1450 CHECK_TRUE(retval == 0);
1451
1452 /*
1453 * Test xlat_unmmap_memory_page() with a valid address
1454 * below the start of init_mmap[0U]. This gives us an address
1455 * below the range mapped by table we retrieved.
1456 */
1457 test_va = init_mmap[0U].base_va + ctx.cfg->base_va;
1458 test_va -= test_helpers_get_rand_in_range(1, PAGE_SIZE - 1);
1459
1460 /* Try to unmap the page/block containing `test_va` */
1461 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1462
1463 /* Verify that the return is as expected */
1464 CHECK_VERBOSE((retval == -EFAULT),
1465 "Testing VA 0x%lx on TTE for VA 0x%lx",
1466 test_va,
1467 init_mmap[1U].base_va + ctx.cfg->base_va);
1468
1469 /* Verify that the TTE remains unchanged */
1470 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1471
1472 /*
1473 * Repeat the process, this time with an address on a page
1474 * after the one mapped by init_mmap[2U]. This gives us an
1475 * address over the range mapped by table we retrieved.
1476 */
1477 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1478 test_va += PAGE_SIZE;
1479 test_va += test_helpers_get_rand_in_range(0,
1480 PAGE_SIZE - 1);
1481
1482 /* Try to unmap the page/block containing `test_va` */
1483 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1484
1485 /* Verify that the return is as expected */
1486 CHECK_VERBOSE((retval == -EFAULT),
1487 "Testing VA 0x%lx on TTE for VA 0x%lx",
1488 test_va,
1489 init_mmap[2U].base_va + ctx.cfg->base_va);
1490
1491 /* Verify that the TTE remains unchanged */
1492 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1493
1494 /*
1495 * Try to unmap an address marked as non-transient
1496 */
1497 tbl_ptr[tte_idx] &= ~(MASK(TRANSIENT_FLAG));
1498 val_tte = tbl_ptr[tte_idx];
1499
1500 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1501 test_va += test_helpers_get_rand_in_range(0, PAGE_SIZE - 1);
1502
1503 /* Try to unmap the page/block containing `test_va` */
1504 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1505
1506 /* Verify that the return is as expected */
1507 CHECK_VERBOSE((retval == -EFAULT),
1508 "Testing VA 0x%lx on a non-transient valid TTE",
1509 test_va);
1510
1511 /* Verify that the TTE remains unchanged */
1512 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1513
1514 /*
1515 * Try to unmap an address marked as invalid.
1516 */
1517 tbl_ptr[tte_idx] = INVALID_DESC;
1518 val_tte = tbl_ptr[tte_idx];
1519
1520 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1521 test_va += test_helpers_get_rand_in_range(0,
1522 PAGE_SIZE - 1);
1523
1524 /* Try to unmap the page/block containing `test_va` */
1525 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1526
1527 /* Verify that the return is as expected */
1528 CHECK_VERBOSE((retval == -EFAULT),
1529 "Testing VA 0x%lx on a ninvalid TTE",
1530 test_va);
1531
1532 /* Verify that the TTE remains unchanged */
1533 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1534 VERBOSE("\n");
1535 }
1536}
1537
1538ASSERT_TEST(xlat_tests_G2, xlat_unmap_memory_page_TC3)
1539{
1540 /***************************************************************
1541 * TEST CASE 3:
1542 *
1543 * Try calling xlat_unmap_memory_page with a NULL
1544 * xlat_llt_info structure.
1545 ***************************************************************/
1546
1547 test_helpers_expect_assert_fail(true);
1548 (void)xlat_unmap_memory_page(NULL, 0ULL);
1549 test_helpers_fail_if_no_assert_failed();
1550}
1551
1552TEST(xlat_tests_G2, xlat_map_memory_page_with_attrs_TC1)
1553{
1554 struct xlat_ctx ctx;
1555 struct xlat_ctx_cfg cfg;
1556 struct xlat_ctx_tbls tbls;
1557 uint64_t start_va;
1558 size_t va_size, granularity;
1559 unsigned int mmap_count;
1560 xlat_addr_region_id_t va_region;
1561 int retval;
1562 struct xlat_mmap_region init_mmap[3U];
1563 unsigned int tbl_idx[3U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001564 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001565
1566 /***************************************************************
1567 * TEST CASE 1:
1568 *
1569 * For each possible end lookup level, create a set transient
1570 * random mappings.
1571 *
1572 * For each possible (va_region, end_lvl) tuple, there will be three
1573 * mmap regions created:
1574 *
1575 * - First region mapped at the beginning of a table whose
1576 * final lookup level is 'end_lvl'
1577 * - Second region mapped at a random index of a table whose
1578 * final lookup level is 'end_lvl'
1579 * - Third region mapped at the end of a table whose
1580 * final lookup level is 'end_lvl'
1581 *
1582 * Then verify that we can map PA areas into the transient
1583 * entries using random attributes and that the generated
1584 * entry is valid.
1585 ***************************************************************/
1586
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001587 mmap_count = 3;
1588 base_lvl = XLAT_TEST_MIN_LVL();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001589
1590 /* The first look-up level that supports blocks is L1 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001591 for (end_lvl = 1; end_lvl <= XLAT_TABLE_LEVEL_MAX; end_lvl++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001592 for (int i = 0U; i < VA_REGIONS; i++) {
1593 va_region = (xlat_addr_region_id_t)i;
1594
1595 start_va = gen_va_space_params_by_lvl(base_lvl,
1596 va_region,
1597 &va_size);
1598
1599 retval = gen_mmap_array_by_level(&init_mmap[0U],
1600 &tbl_idx[0U],
1601 mmap_count,
1602 base_lvl,
1603 end_lvl,
1604 &granularity,
1605 start_va,
1606 false);
1607
1608 /* Verify that the test setup is correct so far */
1609 CHECK_TRUE(retval == 0);
1610
1611 /* Force all the mmap regions to be TRANSIENT */
1612 for (unsigned int j = 0U; j < mmap_count; j++) {
1613 init_mmap[j].attr = MT_TRANSIENT;
1614 }
1615
1616 /* Clean the data structures */
1617 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1618 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1619 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1620
1621 /* Initialize the test structure */
1622 retval = xlat_ctx_cfg_init(&cfg, va_region,
1623 &init_mmap[0U],
1624 mmap_count, va_size);
1625
1626 /* Verify that the test setup is correct so far */
1627 CHECK_TRUE(retval == 0);
1628
1629 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1630 xlat_test_helpers_tbls(),
1631 XLAT_TESTS_MAX_TABLES);
1632
1633 /* Verify that the test setup is correct so far */
1634 CHECK_TRUE(retval == 0);
1635
1636 /*
1637 * For each one of the mmap regions:
1638 * - Generate a random VA within the mmap VA space.
1639 * - generate a set of random attributes.
1640 * - Map a random PA to the generated VA and with
1641 * the generated attributes.
1642 * - call xlat_unmap_memory_page_map_with_attrs() to
1643 * create the mapping.
1644 * - verify that the new entry is valid.
1645 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001646 for (unsigned int j = 0U; j < mmap_count; j++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001647 uint64_t tte, val_tte, attrs, pa, type;
1648 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001649 unsigned int tte_idx;
1650 int tte_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001651 struct xlat_llt_info tbl_info;
1652 uint64_t offset =
1653 test_helpers_get_rand_in_range(0,
1654 init_mmap[i].size - 1);
1655 uint64_t test_va = init_mmap[j].base_va +
1656 ctx.cfg->base_va + offset;
1657
1658 /*
1659 * Perform a table walk to retrieve the table
1660 * where the VA is mapped along with the index
1661 * of the TTE within the table.
1662 */
1663 retval = xlat_test_helpers_table_walk(&ctx,
1664 test_va, &tte,
1665 &tbl_ptr, &tte_lvl,
1666 &tte_idx);
1667
1668 /*
1669 * Verify that the test setup is correct so far
1670 */
1671 CHECK_TRUE(retval == 0);
1672
1673 /* Generate a random set of attributes. */
1674 do {
1675 attrs = xlat_test_helpers_rand_mmap_attrs();
1676 } while (attrs == MT_TRANSIENT);
1677
1678 /*
1679 * Generate the validation TTE. For convenience,
1680 * create an identity mapping.
1681 */
1682 retval = xlat_test_helpers_gen_attrs(&val_tte,
1683 attrs);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001684 pa = init_mmap[j].base_va & XLAT_TEST_GET_PA_MASK();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001685
1686 /*
1687 * Add an arbitrary offset to PA to be passed to
1688 * xlat_map_memory_page_with_attrs()
1689 */
1690 pa += test_helpers_get_rand_in_range(1,
1691 XLAT_BLOCK_SIZE(end_lvl) - 1);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001692 val_tte |= set_oa_to_tte(pa &
1693 XLAT_ADDR_MASK(end_lvl));
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001694
1695 /* The TTE will be a transient one */
1696 val_tte |= (1ULL <<
1697 TRANSIENT_FLAG_SHIFT);
1698
1699 /* TTE type */
1700 type = (end_lvl == XLAT_TABLE_LEVEL_MAX) ?
1701 PAGE_DESC :
1702 BLOCK_DESC;
1703 val_tte |= type;
1704
1705 /* Verify the test setup */
1706 CHECK_TRUE(retval == 0);
1707
1708 /*
1709 * Retrieve the xlat_llt_info structure needed
1710 * to feed xlat_map_memory_page_with_attrs()
1711 */
1712 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
1713 test_va);
1714
1715 /*
1716 * Verify that the test setup is correct so far
1717 */
1718 CHECK_TRUE(retval == 0);
1719
1720 /*
1721 * Try to map the PA with the attributes to the
1722 * `test_va`
1723 */
1724 retval = xlat_map_memory_page_with_attrs(
1725 &tbl_info,
1726 test_va, pa, attrs);
1727
1728 /* Verify that the return is as expected */
1729 CHECK_VERBOSE((retval == 0),
1730 "Mapping PA 0x%.16lx to VA 0x%.16lx with attrs 0x%lx",
1731 pa, test_va, attrs);
1732 CHECK_TRUE(retval == 0);
1733
1734 /*
1735 * Verify that the generated TTE matches
1736 * the validation one.
1737 */
1738 CHECK_VERBOSE((val_tte == tbl_ptr[tte_idx]),
1739 "Verifying TTE 0x%.16lx against 0x%.16lx",
1740 tbl_ptr[tte_idx], val_tte);
1741 }
1742 VERBOSE("\n");
1743 }
1744 }
1745}
1746
1747TEST(xlat_tests_G2, xlat_map_memory_page_with_attrs_TC2)
1748{
1749 struct xlat_ctx ctx;
1750 struct xlat_ctx_cfg cfg;
1751 struct xlat_ctx_tbls tbls;
1752 uint64_t start_va, test_va, test_pa;
1753 size_t va_size, granularity;
1754 unsigned int mmap_count;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001755 unsigned int tte_idx;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001756 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001757 int tte_lvl, retval;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001758 struct xlat_mmap_region init_mmap[3U];
1759 unsigned int tbl_idx[3U];
1760 struct xlat_llt_info tbl_info;
1761 uint64_t tte, val_tte;
1762 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001763 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001764 unsigned int pa_range_bits_arr[] = {
1765 PARANGE_0000_WIDTH, PARANGE_0001_WIDTH, PARANGE_0010_WIDTH,
1766 PARANGE_0011_WIDTH, PARANGE_0100_WIDTH, PARANGE_0101_WIDTH,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001767 PARANGE_0110_WIDTH
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001768 };
1769 unsigned int parange_index = test_helpers_get_rand_in_range(0,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001770 ARRAY_SIZE(pa_range_bits_arr) - 1U);
1771 uint64_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001772
1773 /***************************************************************
1774 * TEST CASE 2:
1775 *
1776 * Generate a mmap region with a set of transient invalid
1777 * mappings. Then run a set of negative tests:
1778 *
1779 * - Try addresses below and above the range mapped by the
1780 * xlat_llt_info structure on a transient-invalid entry.
1781 * - Try mapping a PA lager than the maximum supported PA
1782 * to a transient-invalid entry.
1783 * - Try mapping to a transient-valid entry.
1784 * - Try mapping to a valid entry.
1785 * - Try mapping to an invalid entry.
1786 ***************************************************************/
1787
1788 /*
1789 * Pick up a base and end levels for the translation tables.
1790 * The leves are arbitrary. Just to have a VA space enough
1791 * for the tests.
1792 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001793 base_lvl = XLAT_TEST_MIN_LVL();
1794 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001795
1796 mmap_count = 3U;
1797
1798 for (int i = 0U; i < VA_REGIONS; i++) {
1799 va_region = (xlat_addr_region_id_t)i;
1800
1801 start_va = gen_va_space_params_by_lvl(base_lvl,
1802 va_region, &va_size);
1803
1804 /*
1805 * We generate the mmap regions to use. We will be interested
1806 * in init_mmap[1] for the transient-invalid tests and in
1807 * init_mmap[2] for the rest of tests.
1808 */
1809 retval = gen_mmap_array_by_level(&init_mmap[0U], &tbl_idx[0U],
1810 mmap_count, base_lvl, end_lvl,
1811 &granularity,
1812 start_va, false);
1813
1814 /* Verify that the test setup is correct so far */
1815 CHECK_TRUE(retval == 0);
1816
1817 /* Force init_mmap[1] to be TRANSIENT */
1818 init_mmap[1U].attr = MT_TRANSIENT;
1819
1820 /* Clean the data structures */
1821 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1822 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1823 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1824
1825 /* Initialize the test structure */
1826 retval = xlat_ctx_cfg_init(&cfg, va_region, &init_mmap[0U],
1827 mmap_count, va_size);
1828
1829 /* Verify that the test setup is correct so far */
1830 CHECK_TRUE(retval == 0);
1831
1832 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1833 xlat_test_helpers_tbls(),
1834 XLAT_TESTS_MAX_TABLES);
1835
1836 /* Verify that the test setup is correct so far */
1837 CHECK_TRUE(retval == 0);
1838
1839 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1840
1841 /*
1842 * Retrieve the xlat_llt_info structure needed to feed
1843 * xlat_map_memory_page_with_attrs().
1844 */
1845 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1846
1847 /* Verify that the test setup is correct so far */
1848 CHECK_TRUE(retval == 0);
1849
1850 /*
1851 * Test xlat_map_memory_page_with_attrs() with a valid address
1852 * within init_mmap[0]. This gives us an address
1853 * below the range mapped by table we retrieved (which belongs
1854 * to init_mmap[1]). For simplicity, set the attributes and
1855 * the PA both to 0x0.
1856 */
1857 test_va = init_mmap[0U].base_va + ctx.cfg->base_va;
Soby Mathewbddaba12023-04-22 03:34:00 +00001858 test_va += test_helpers_get_rand_in_range(0, init_mmap[0U].size - 1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001859
1860 /* Try to map to the page/block containing `test_va` */
1861 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1862 0ULL, 0ULL);
1863
1864 /* Verify that the return is as expected */
1865 CHECK_VERBOSE((retval == -EFAULT),
1866 "Testing VA 0x%.16lx on TTE for VA 0x%.16lx",
1867 test_va,
1868 init_mmap[1U].base_va + ctx.cfg->base_va);
1869
1870 /*
1871 * Repeat the process, this time with an address on a page
1872 * mapped by init_mmap[2]. This gives us an
1873 * address over the range mapped by table we retrieved.
1874 */
1875 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1876 test_va += test_helpers_get_rand_in_range(0,
1877 PAGE_SIZE - 1);
1878
1879 /* Try to map to the page/block containing `test_va` */
1880 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1881 0ULL, 0ULL);
1882
1883 /* Verify that the return is as expected */
1884 CHECK_VERBOSE((retval == -EFAULT),
1885 "Testing VA 0x%.16lx on TTE for VA 0x%.16lx",
1886 test_va,
1887 init_mmap[2U].base_va + ctx.cfg->base_va);
1888
1889 /*
1890 * Test with a PA larger than the maximum PA supported.
1891 */
1892
1893 /* Configure a random maximum PA supported */
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01001894 xlat_test_helpers_set_parange(parange_index);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001895 test_pa =
1896 (1ULL << pa_range_bits_arr[parange_index]) + PAGE_SIZE;
1897
1898 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1899
1900 /*
1901 * Perform a table walk to retrieve the table where the VA
1902 * is mapped along with the index of the TTE within the table.
1903 */
1904 retval = xlat_test_helpers_table_walk(&ctx, test_va, &tte,
1905 &tbl_ptr, &tte_lvl,
1906 &tte_idx);
1907
1908 /* Verify that the test setup is correct so far */
1909 CHECK_TRUE(retval == 0);
1910
1911 /*
1912 * Take a snapshot of the TTE. This will be used to verify
1913 * that the TTE hasn't been altered.
1914 */
1915 val_tte = tbl_ptr[tte_idx];
1916
1917 /* Get a random address to test */
1918 test_va += test_helpers_get_rand_in_range(0, PAGE_SIZE - 1);
1919
1920 /* Try to map the PA to the page/block containing `test_va` */
1921 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1922 test_pa, 0ULL);
1923
1924 /* Verify that the return is as expected */
1925 CHECK_VERBOSE((retval == -EFAULT),
1926 "Testing PA 0x%.16lx on with a max supported PA of 0x%.16llx",
1927 test_pa,
1928 (1ULL << pa_range_bits_arr[parange_index]) - 1ULL);
1929
1930 /* Verify that the TTE remains unchanged */
1931 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1932
1933 /* Restore the maximum supported PA size for next tests */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001934 host_write_sysreg("id_aa64mmfr0_el1", id_aa64mmfr0_el1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001935
1936 /* The rest of the tests will be based on init_mmap[2] */
1937 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1938
1939 /*
1940 * Perform a table walk to retrieve the table where the VA
1941 * is mapped along with the index of the TTE within the table.
1942 */
1943 retval = xlat_test_helpers_table_walk(&ctx, test_va, &tte,
1944 &tbl_ptr, &tte_lvl,
1945 &tte_idx);
1946
1947 /* Verify that the test setup is correct so far */
1948 CHECK_TRUE(retval == 0);
1949
1950 /*
Soby Mathewbddaba12023-04-22 03:34:00 +00001951 * Retrieve the xlat_llt_info structure needed to feed
1952 * xlat_map_memory_page_with_attrs().
1953 */
1954 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1955
1956 /* Verify that the test setup is correct so far */
1957 CHECK_TRUE(retval == 0);
1958
1959 /*
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001960 * Make the TTEs of the mapped region, which is expected
1961 * to be valid, transient valid.
1962 */
1963 tbl_ptr[tte_idx] |= (1ULL << TRANSIENT_FLAG_SHIFT);
1964
1965 /*
1966 * Take a snapshot of the TTE. This will be used to verify
1967 * that the TTE hasn't been altered.
1968 */
1969 val_tte = tbl_ptr[tte_idx];
1970
1971 /*
Soby Mathewbddaba12023-04-22 03:34:00 +00001972 * Now try to map a valid VA. In this case the associated
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001973 * TTE will contain a transient valid mapping.
1974 */
1975 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1976 test_va += test_helpers_get_rand_in_range(0, PAGE_SIZE - 1);
1977
1978 /* Try to map to the page/block containing `test_va` */
1979 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1980 0ULL, 0ULL);
1981
1982 /* Verify that the return is as expected */
1983 CHECK_VERBOSE((retval == -EFAULT),
1984 "Testing VA 0x%.16lx on a transient valid TTE",
1985 test_va);
1986
1987 /* Verify that the TTE remains unchanged */
1988 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1989
1990 /*
1991 * Repeat the last test but after clearing the TRANSIENT
1992 * flag from the TTE. This will test the behaviour with
1993 * a non transient TTE.
1994 */
1995 tbl_ptr[tte_idx] &= ~(1ULL << TRANSIENT_FLAG_SHIFT);
1996 val_tte = tbl_ptr[tte_idx];
1997
1998 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1999 test_va += test_helpers_get_rand_in_range(0, PAGE_SIZE - 1);
2000
2001 /* Try to map to the page/block containing `test_va` */
2002 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
2003 0ULL, 0ULL);
2004
2005 /* Verify that the return is as expected */
2006 CHECK_VERBOSE((retval == -EFAULT),
2007 "Testing VA 0x%.16lx on a valid TTE",
2008 test_va);
2009
2010 /* Verify that the TTE remains unchanged */
2011 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
2012
2013 /*
2014 * Repeat the last test on an INVALID TTE.
2015 */
2016 tbl_ptr[tte_idx] = 0ULL;
2017 val_tte = 0ULL;
2018
2019 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
2020 test_va += test_helpers_get_rand_in_range(0,
2021 PAGE_SIZE - 1);
2022
2023 /* Try to map to the page/block containing `test_va` */
2024 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
2025 0ULL, 0ULL);
2026
2027 /* Verify that the return is as expected */
2028 CHECK_VERBOSE((retval == -EFAULT),
2029 "Testing VA 0x%.16lx on an invalid TTE",
2030 test_va);
2031
2032 /* Verify that the TTE remains unchanged */
2033 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
2034
2035 VERBOSE("\n");
2036 }
2037}
2038
2039ASSERT_TEST(xlat_tests_G2, xlat_map_memory_page_with_attrs_TC3)
2040{
2041 /***************************************************************
2042 * TEST CASE 3:
2043 *
2044 * Try calling xlat_map_memory_page_with_attrs with a NULL
2045 * xlat_llt_info structure.
2046 ***************************************************************/
2047
2048 test_helpers_expect_assert_fail(true);
2049 (void)xlat_map_memory_page_with_attrs(NULL, 0ULL, 0ULL, 0ULL);
2050 test_helpers_fail_if_no_assert_failed();
2051}
2052
2053/* Helper function to validate ttbrx_el2 registers */
2054static void validate_ttbrx_el2(struct xlat_ctx *ctx)
2055{
2056 uint64_t expected_ttbrx, ttbrx;
2057 xlat_addr_region_id_t va_region;
2058
2059 assert(ctx != NULL);
2060
2061 va_region = ctx->cfg->region;
2062
2063 /* BADDR */
2064 expected_ttbrx = ((uint64_t)&ctx->tbls->tables[0U]) &
2065 MASK(TTBRx_EL2_BADDR);
2066
2067 ttbrx = read_ttbr1_el2();
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002068 if (va_region == VA_LOW_REGION) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002069 ttbrx = read_ttbr0_el2();
2070
2071 /*
2072 * CnP bit. It is expected that the xlat library will
2073 * automatically set this bit for the low region.
2074 */
2075 expected_ttbrx |= (1ULL << TTBRx_EL2_CnP_SHIFT);
2076 }
2077
2078 CHECK_VERBOSE((expected_ttbrx == ttbrx),
2079 "Expected TTBR%c_EL2: 0x%lx - Received: 0x%lx",
2080 (unsigned int)va_region + '0',
2081 expected_ttbrx, ttbrx);
2082}
2083
2084/* Helper function to validate TCR_EL2 register */
2085static void validate_tcr_el2(struct xlat_ctx *low_ctx,
2086 struct xlat_ctx *high_ctx)
2087{
2088 uint64_t exp_tcr, tcr;
2089 size_t t0sz, t1sz;
2090 unsigned int parange;
2091
2092 tcr = read_tcr_el2();
2093
2094 /*
2095 * Calculate the VA space size for both contexts based on
2096 * the TCR_EL2 register.
2097 */
2098 t0sz = ((size_t)1) << (64U - EXTRACT(TCR_EL2_T0SZ, tcr));
2099 t1sz = ((size_t)1) << (64U - EXTRACT(TCR_EL2_T1SZ, tcr));
2100
2101 /* Validate the VA space size of the contexts */
2102 CHECK_VERBOSE((t0sz == low_ctx->cfg->max_va_size),
2103 "Check VA space size for Low Region: 0x%lx == 0x%lx",
2104 t0sz, low_ctx->cfg->max_va_size);
2105 CHECK_VERBOSE((t1sz == high_ctx->cfg->max_va_size),
2106 "Check VA space size for High Region: 0x%lx == 0x%lx",
2107 t1sz, high_ctx->cfg->max_va_size);
2108
2109 /* Mask out TxSZ fields. We have already validated them */
2110 tcr &= ~(MASK(TCR_EL2_T0SZ) | MASK(TCR_EL2_T1SZ));
2111
2112 /*
2113 * Inner and outher cacheability attributes as expected by RMM
2114 * for all the contexts.
2115 */
2116 exp_tcr = TCR_EL2_IRGN0_WBWA | TCR_EL2_ORGN0_WBWA;
2117 exp_tcr |= TCR_EL2_IRGN1_WBWA | TCR_EL2_ORGN1_WBWA;
2118
2119 /* Shareability as expected by RMM for all the contexts */
2120 exp_tcr |= TCR_EL2_SH0_IS | TCR_EL2_SH1_IS;
2121
2122 /* Granule size for all the contexts. Only 4KB supported */
2123 exp_tcr |= TCR_EL2_TG0_4K | TCR_EL2_TG1_4K;
2124
2125 /* Hierarchical permissions */
2126 exp_tcr |= TCR_EL2_AS | TCR_EL2_HPD0 | TCR_EL2_HPD1;
2127
2128 /*
2129 * Xlat library configures TCR_EL2.IPS to the max
2130 * supported by the PE.
2131 */
2132 parange = EXTRACT(ID_AA64MMFR0_EL1_PARANGE, read_id_aa64mmfr0_el1());
2133 exp_tcr |= INPLACE(TCR_EL2_IPS, parange);
2134
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002135 if (is_feat_lpa2_4k_present() == true) {
2136 exp_tcr |= (TCR_EL2_DS_LPA2_EN
2137 | TCR_EL2_SH0_IS
2138 | TCR_EL2_SH1_IS);
2139 }
2140
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002141 /* Validate tcr_el2*/
2142 CHECK_VERBOSE((exp_tcr == tcr),
2143 "Validate TCR_EL2 against expected value: Read 0x%.16lx - Expected 0x%.16lx",
2144 tcr, exp_tcr);
2145}
2146
2147TEST(xlat_tests_G2, xlat_arch_setup_mmu_cfg_TC1)
2148{
2149 struct xlat_ctx ctx[2U];
2150 struct xlat_ctx_cfg cfg[2U];
2151 struct xlat_ctx_tbls tbls[2U];
2152 uint64_t *base_tbl[2U], *xlat_tables;
2153 uint64_t start_va, end_va;
2154 xlat_addr_region_id_t va_region;
2155 int retval;
2156 struct xlat_mmap_region init_mmap[2U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002157 unsigned int pa_index, max_pa_index;
2158 bool lpa2 = is_feat_lpa2_4k_present();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002159 unsigned int pa_range_bits_arr[] = {
2160 PARANGE_0000_WIDTH, PARANGE_0001_WIDTH, PARANGE_0010_WIDTH,
2161 PARANGE_0011_WIDTH, PARANGE_0100_WIDTH, PARANGE_0101_WIDTH,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002162 PARANGE_0110_WIDTH
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002163 };
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002164 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002165
2166 /***************************************************************
2167 * TEST CASE 1:
2168 *
2169 * Generate a translation context for each region and configure
2170 * the MMU registers based on both contexts. Verify that the
2171 * right parameters have been configured.
2172 ***************************************************************/
2173
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002174 max_pa_index = ARRAY_SIZE(pa_range_bits_arr);
2175 max_pa_index = (lpa2 == true) ? max_pa_index : max_pa_index - 1U;
2176 pa_index = test_helpers_get_rand_in_range(0, max_pa_index - 1U);
2177
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002178 /* Clean the data structures */
2179 memset((void *)&ctx, 0, sizeof(struct xlat_ctx) * 2U);
2180 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg) * 2U);
2181 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls) * 2U);
2182
2183 /* Configure a random maximum PA supported */
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002184 xlat_test_helpers_set_parange(pa_index);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002185
2186 for (int i = 0U; i < VA_REGIONS; i++) {
2187 va_region = (xlat_addr_region_id_t)i;
2188
2189 xlat_tables = xlat_test_helpers_tbls();
2190 /* Use half of the available tables for each region */
2191 base_tbl[i] = &xlat_tables[(i * XLAT_TESTS_MAX_TABLES *
2192 XLAT_TABLE_ENTRIES) >> 1U];
2193 /* VA space boundaries */
2194 start_va = xlat_test_helpers_get_start_va(va_region,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002195 max_va_size);
2196 end_va = start_va + max_va_size - 1ULL;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002197
2198 /* Generate only a single mmap region for each region */
2199 xlat_test_helpers_rand_mmap_array(&init_mmap[i], 1U, start_va, end_va);
2200
2201 retval = xlat_ctx_cfg_init(&cfg[i], va_region, &init_mmap[i],
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002202 1U, max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002203 CHECK_TRUE(retval == 0);
2204
2205 retval = xlat_ctx_init(&ctx[i], &cfg[i], &tbls[i],
2206 base_tbl[i], XLAT_TESTS_MAX_TABLES >> 1U);
2207 CHECK_TRUE(retval == 0);
2208
2209 /* Initialize MMU for the given context */
2210 retval = xlat_arch_setup_mmu_cfg(&ctx[i]);
2211
2212 /* Verify that the MMU has been configured */
2213 CHECK_TRUE(retval == 0);
2214
2215 /* Validate TTBR_EL2 for each context */
2216 validate_ttbrx_el2(&ctx[i]);
2217 }
2218
2219 /* Validate TCR_EL2 for both contexts at the same time */
2220 validate_tcr_el2(&ctx[0U], &ctx[1U]);
2221}
2222
2223TEST(xlat_tests_G2, xlat_arch_setup_mmu_cfg_TC2)
2224{
2225 struct xlat_ctx ctx;
2226 struct xlat_ctx_cfg cfg;
2227 struct xlat_ctx_tbls tbls;
2228 uint64_t start_va, end_va;
2229 int retval;
2230 struct xlat_mmap_region init_mmap;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002231 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002232
2233 /***************************************************************
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002234 * TEST CASE 2:
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002235 *
2236 * Generate a valid translation context for one of the regions
2237 * and overwrite it to test different failure conditions on
2238 * xlat_arch_setup_mmu_cfg():
2239 *
2240 * - Call xlat_arch_setup_mmu_cfg() with the MMU enabled.
2241 * - Call xlat_arch_setup_mmu_cfg() with an uninitialized
2242 * context configuration.
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002243 * - Call xlat_arch_setup_mmu_cfg() for a CPU which
2244 * does not have support for 4KB granularity.
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002245 * - Call xlat_arch_setup_mmu_cfg() for a CPU which
2246 * does not support FEAT_LPA2 but reports a PA
2247 * size larger than 48 bits.
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002248 ***************************************************************/
2249
2250 /* Clean the data structures */
2251 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
2252 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
2253 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
2254
2255 /* VA space boundaries */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002256 start_va = xlat_test_helpers_get_start_va(VA_LOW_REGION, max_va_size);
2257 end_va = start_va + max_va_size - 1ULL;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002258
2259 /* Generate only a single mmap region for each region */
2260 xlat_test_helpers_rand_mmap_array(&init_mmap, 1U, start_va, end_va);
2261
2262 retval = xlat_ctx_cfg_init(&cfg, VA_LOW_REGION, &init_mmap,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002263 1U, max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002264 CHECK_TRUE(retval == 0);
2265
2266 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
2267 xlat_test_helpers_tbls(),
2268 XLAT_TESTS_MAX_TABLES);
2269 CHECK_TRUE(retval == 0);
2270
2271 /* Force the MMU enblement */
2272 xlat_enable_mmu_el2();
2273
2274 /* Try to initialize MMU for the given context */
2275 retval = xlat_arch_setup_mmu_cfg(&ctx);
2276
2277 /* Verify that the MMU has failed to be initialized */
2278 CHECK_TRUE(retval == -EPERM);
2279
2280 /* Restore SCTLR_EL2 to disable the MMU */
2281 write_sctlr_el2(0ULL);
2282
2283 /* Force the context to be uninitialized */
2284 ctx.cfg->initialized = false;
2285
2286 /* Try to initialize MMU for the given context */
2287 retval = xlat_arch_setup_mmu_cfg(&ctx);
2288
2289 /* Verify that the MMU has failed to be initialized */
2290 CHECK_TRUE(retval == -EINVAL);
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002291
2292 /* Restore the context initialized flag */
2293 ctx.cfg->initialized = true;
2294
2295 /* Force the architecture to report 4K granularity as not available */
2296 host_write_sysreg("id_aa64mmfr0_el1",
2297 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5U) |
2298 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2299 ID_AA64MMFR0_EL1_TGRAN4_NOT_SUPPORTED));
2300
2301 /* Try to initialize MMU for the given context */
2302 retval = xlat_arch_setup_mmu_cfg(&ctx);
2303
2304 /* Verify that the MMU has failed to be initialized */
2305 CHECK_TRUE(retval == -EPERM);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002306
2307 /*
2308 * Force the architecture to report 4K granularity available without
2309 * support for LPA2 but with an PA size of more than 48 bits.
2310 * Note that this scenario should never happen on the architecture
2311 * however, the library still checks for this.
2312 */
2313 host_write_sysreg("id_aa64mmfr0_el1",
2314 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 6U) |
2315 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2316 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED));
2317
2318 /* Try to initialize MMU for the given context */
2319 retval = xlat_arch_setup_mmu_cfg(&ctx);
2320
2321 /* Verify that the MMU has failed to be initialized */
2322 CHECK_TRUE(retval == -ENOMEM);
2323
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002324}
2325
2326ASSERT_TEST(xlat_tests_G2, xlat_arch_setup_mmu_cfg_TC3)
2327{
2328 /***************************************************************
2329 * TEST CASE 3:
2330 *
2331 * Test xlat_arch_setup_mmu_cfg() with a NULL context.
2332 ***************************************************************/
2333
2334 test_helpers_expect_assert_fail(true);
2335 (void)xlat_arch_setup_mmu_cfg(NULL);
2336 test_helpers_fail_if_no_assert_failed();
2337}
2338
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002339ASSERT_TEST(xlat_tests_G2, xlat_arch_setup_mmu_cfg_TC4)
2340{
2341 struct xlat_ctx ctx;
2342 struct xlat_ctx_cfg cfg;
2343 struct xlat_ctx_tbls tbls;
2344 struct xlat_mmap_region init_mmap;
2345
2346 /***************************************************************
2347 * TEST CASE 4:
2348 *
2349 * Test xlat_arch_setup_mmu_cfg() with a context in which the
2350 * configuration is NULL.
2351 *
2352 * This test reuses xlat_get_llt_from_va_prepare_assertion()
2353 * in order to generate an initial valid context.
2354 ***************************************************************/
2355
2356 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
2357
2358 /* Force the context configuration to NULL */
2359 ctx.cfg = NULL;
2360
2361 test_helpers_expect_assert_fail(true);
2362 (void)xlat_arch_setup_mmu_cfg(&ctx);
2363 test_helpers_fail_if_no_assert_failed();
2364}
2365
2366ASSERT_TEST(xlat_tests_G2, xlat_arch_setup_mmu_cfg_TC5)
2367{
2368 struct xlat_ctx ctx;
2369 struct xlat_ctx_cfg cfg;
2370 struct xlat_ctx_tbls tbls;
2371 struct xlat_mmap_region init_mmap;
2372
2373 /***************************************************************
2374 * TEST CASE 5:
2375 *
2376 * Test xlat_arch_setup_mmu_cfg() with a context in which the
2377 * 'tbls' structure is NULL.
2378 *
2379 * This test reuses xlat_get_llt_from_va_prepare_assertion()
2380 * in order to generate an initial valid context.
2381 ***************************************************************/
2382
2383 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
2384
2385 /* Force the context tables structure to NULL */
2386 ctx.tbls = NULL;
2387
2388 test_helpers_expect_assert_fail(true);
2389 (void)xlat_arch_setup_mmu_cfg(&ctx);
2390 test_helpers_fail_if_no_assert_failed();
2391}
2392
2393TEST(xlat_tests_G2, xlat_get_oa_from_tte_TC1)
2394{
2395 uint64_t test_tte, val_addr, output_addr;
2396
2397 /***************************************************************
2398 * TEST CASE 1:
2399 *
2400 * Test xlat_get_oa_from_tte() with 4K granularity and with and
2401 * without LPA2 support.
2402 ***************************************************************/
2403
2404 /*
2405 * Generate a random TTE to test. We are not concerned about the
2406 * validity of the TTE or about any bitfield that is not part of
2407 * the output address, as xlat_get_oa_from_tte() is expected to
2408 * just ignore those.
2409 */
2410 test_tte = ~0ULL;
2411
2412 /* Test with FEAT_LPA2 available */
2413 host_write_sysreg("id_aa64mmfr0_el1",
2414 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 6UL) |
2415 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2416 ID_AA64MMFR0_EL1_TGRAN4_LPA2));
2417
2418 /* Generate the validation address from the test TTE */
2419 val_addr = test_tte & BIT_MASK_ULL(TTE_OA_BIT_49_LPA2, OA_SHIFT);
2420 val_addr |= INPLACE(OA_BITS_50_51, EXTRACT(TTE_OA_BITS_50_51, test_tte));
2421
2422 output_addr = xlat_get_oa_from_tte(test_tte);
2423
2424 CHECK_VERBOSE((val_addr == output_addr),
2425 "Test xlat_get_oa_from_tte, LPA2 supported: OA = %p - Expected = %p",
2426 (void *)output_addr, (void *)val_addr);
2427
2428 /* Repeat the test, by disabling support for FEAT_LPA2 this time */
2429 host_write_sysreg("id_aa64mmfr0_el1",
2430 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5U) |
2431 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2432 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED));
2433
2434 /* Generate the validation address */
2435 val_addr = test_tte & BIT_MASK_ULL(TTE_OA_MSB, OA_SHIFT);
2436
2437 output_addr = xlat_get_oa_from_tte(test_tte);
2438
2439 CHECK_VERBOSE((val_addr == output_addr),
2440 "Test xlat_get_oa_from_tte, LPA2 not supported: OA = %p - Expected = %p",
2441 (void *)output_addr, (void *)val_addr);
2442}
2443
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002444IGNORE_TEST(xlat_tests_G2, xlat_write_tte_TC1)
2445{
2446 /*
2447 * xlat_write_tte() is implemented as an assembler function
2448 * for target AArch64 Architecture. There is a C stub for the
2449 * fake_host platform which we do not need to test.
2450 *
2451 * This test can therefore be ignored.
2452 */
2453
2454 TEST_EXIT;
2455}
2456
2457IGNORE_TEST(xlat_tests_G2, xlat_read_tte_TC1)
2458{
2459 /*
2460 * xlat_read_tte() is implemented as an assembler function
2461 * for target AArch64 Architecture. There is a C stub for the
2462 * fake_host platform which we do not need to test.
2463 *
2464 * This test can therefore be ignored.
2465 */
2466
2467 TEST_EXIT;
2468}
2469
2470IGNORE_TEST(xlat_tests_G2, xlat_enable_mmu_el2_TC1)
2471{
2472 /*
2473 * xlat_enable_mmu_el2() is implemented as an assembler function
2474 * for target AArch64 Architecture. There is a C stub for the
2475 * fake_host platform which we do not need to test.
2476 *
2477 * This test can therefore be ignored.
2478 */
2479
2480 TEST_EXIT;
2481}