blob: c25c26e43bbff781f38f9f4cd6032fab92d909be [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
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +010025/*
26 * Generate VA space parameters given a walk start level and a region.
27 * The VA returned will fit in a single table of level `level`, so that
28 * there translation can start at that given level.
29 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +010030static uint64_t gen_va_space_params_by_lvl(int level,
31 xlat_addr_region_id_t region,
32 size_t *va_size)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +010033{
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +010034 assert(level >= XLAT_TEST_MIN_LVL());
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +010035 assert(level <= XLAT_TABLE_LEVEL_MAX);
36 assert(va_size != NULL);
37
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +010038 *va_size = (1ULL << XLAT_ADDR_SHIFT(level)) *
39 XLAT_GET_TABLE_ENTRIES(level);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +010040
41 return xlat_test_helpers_get_start_va(region, *va_size);
42}
43
44/*
45 * Generate a mmap array containing a set of mmap regions defined by
46 * 'start_va', 'last_lvl' and 'offset'. The mmap array will have
47 * three regions:
48 *
49 * - First region mapped at the beginning of a table whose final
50 * lookup level is 'last_lvl'. This region will be descendant of
51 * an entry at the beginning of a table at level 'first_lvl'.
52 * - Second region mapped at a random index of a table whose final
53 * lookup level is 'last_lvl'. This region will be descendant of
54 * an entry at a random index of a table at level 'first_lvl'.
55 * - Third region mapped at the end of a table whose final
56 * lookup level is 'last_lvl'. This region will be descendant of
57 * an entry at the final entry of a table at level 'first_lvl'.
58 *
59 * ┌──────────┐
60 * ┌───────────────┤ First │
61 * │ │ Region │
62 * │ ├──────────┤
63 * │ │ │
64 * │ │ │
65 * │ │ │
66 * │ │ │
67 * │ │ │
68 * │ │ │
69 * │ │ │
70 * ┌──────────────┐ │ │ │
71 * │ │ │ │ │
72 * │ First entry ├───────┘ │ │
73 * ├──────────────┤ │ │
74 * │ Second entry │ │ │
75 * │ (Reserved) │ └──────────┘
76 * │ │
77 * ├──────────────┤
78 * │ │ ┌──────────┐
79 * │ │ │ │
80 * │ │ │ │
81 * │ │ │ │
82 * ├──────────────┤ ├──────────┤
83 * │ Second │ │ Second │
84 * │ Region ├────────────────────────┤ Region │
85 * ├──────────────┤ ├──────────┤
86 * │ │ │ │
87 * │ │ │ │
88 * │ │ │ │
89 * │ │ │ │
90 * │ │ │ │
91 * │ │ │ │
92 * ├──────────────┤ └──────────┘
93 * │ │
94 * │ Third Region ├───────┐
95 * └──────────────┘ │ ┌─────────┐
96 * First Level │ │ │
97 * │ │ │
98 * │ │ │
99 * │ │ │
100 * │ │ │
101 * │ │ │
102 * │ │ │
103 * │ │ │
104 * │ │ │
105 * │ │ │
106 * │ │ │
107 * │ │ │
108 * │ │ │
109 * │ ├─────────┤
110 * └─────────────────┤ Third |
111 * | region │
112 * └─────────┘
113 * Last level
114 *
115 * For all the mmap regions, the granularity (returned in *granularity) is
116 * setup to the minimum granularity needed to map a block at level 'last_lvl'.
117 * The size of the mmap region is setup to the same as the granularity.
118 *
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100119 * This function caters for the reduced number of entries on the
120 * tables at level -1.
121 *
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100122 * This function also returns :
123 * - An array ('tbl_idxs') with the expected indexes mapping
124 * the regions at the last level table.
125 */
126static int gen_mmap_array_by_level(xlat_mmap_region *mmap,
127 unsigned int *tbl_idxs,
128 unsigned int mmap_size,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100129 int first_lvl,
130 int last_lvl,
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100131 size_t *granularity,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100132 uint64_t start_va,
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100133 bool allow_transient)
134{
135 uint64_t attrs;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100136 uint64_t mmap_start_va = start_va;
137 unsigned int max_table_entries = XLAT_GET_TABLE_ENTRIES(first_lvl);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100138
139 assert(mmap_size >= 3U);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100140 assert(last_lvl > XLAT_TEST_MIN_LVL());
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100141 assert(last_lvl <= XLAT_TABLE_LEVEL_MAX);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100142 assert(first_lvl >= XLAT_TEST_MIN_LVL());
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100143 assert(first_lvl <= last_lvl);
144 assert(mmap != NULL);
145 assert(tbl_idxs != NULL);
146 assert(granularity != NULL);
147
148 /* Generate a mapping at the beginning of the table */
149 tbl_idxs[0U] = 0U;
150
151 /*
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100152 * Generate a mapping in a random position of the table.
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100153 * The entry after the first one will always be left intentionally
154 * unused.
155 */
156 tbl_idxs[1U] = test_helpers_get_rand_in_range(2,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100157 (max_table_entries - 2));
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100158
159 /* Generate a mapping at the end of the table */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100160 tbl_idxs[2U] = max_table_entries - 1U;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100161
162 do {
163 attrs = xlat_test_helpers_rand_mmap_attrs();
164 } while ((attrs == MT_TRANSIENT) && (allow_transient == false));
165
166 *granularity = XLAT_BLOCK_SIZE(last_lvl);
167
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100168 for (unsigned int i = 0U; i < 3U; i++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100169 mmap[i].base_va = mmap_start_va;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100170 if (first_lvl < last_lvl) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100171 /*
172 * Add an offset to the mmap region base VA so that
173 * this region will be mapped to a TTE in the
174 * `first_lvl` table at the same index as specified
175 * in tbl_idxs[].
176 */
177 mmap[i].base_va += tbl_idxs[i] *
178 XLAT_BLOCK_SIZE(first_lvl);
179 }
180
181 mmap[i].base_va += (tbl_idxs[i] * (*granularity));
182
183 /*
184 * PA can be any address (as long as there are not overlaps,
185 * for which there is a specific test). For simplicity,
186 * create an identity mapping using the base_va for the PA.
187 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100188 mmap[i].base_pa = mmap[i].base_va & XLAT_TEST_GET_PA_MASK();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100189 mmap[i].size = *granularity;
190 mmap[i].attr = attrs;
191 mmap[i].granularity = *granularity;
192 }
193
194 return 0;
195}
196
197/*
198 * Given a context and a set of expected indexes and levels for the last walk,
199 * validate that the translation tables in the context are valid.
200 * Note that this function expects a valid and initialized context.
201 */
202static void validate_xlat_tables(xlat_ctx *ctx, unsigned int *expected_idxs,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100203 int expected_level)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100204{
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100205 uint64_t tte, tte_oa, attrs, upper_attrs, lower_attrs, type;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100206 uint64_t exp_upper_attrs, exp_lower_attrs;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100207 unsigned int index, granularity, addr_offset;
208 uint64_t test_va, pa, pa_mask;
209 int level, retval;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100210
211 assert(ctx != NULL);
212 assert(expected_idxs != NULL);
213
214 for (unsigned int i = 0U; i < ctx->cfg->mmap_regions; i++) {
215 granularity = ctx->cfg->mmap[i].granularity;
216 addr_offset = test_helpers_get_rand_in_range(0,
217 granularity - 1U);
218 test_va = ctx->cfg->base_va + ctx->cfg->mmap[i].base_va +
219 addr_offset;
220 pa = ctx->cfg->mmap[i].base_pa + addr_offset;
221
222 /* Perform a table walk */
223 retval = xlat_test_helpers_table_walk(ctx, test_va,
224 &tte, NULL, &level,
225 &index);
226
227 /* Return value */
228 CHECK_VERBOSE((retval == 0),
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100229 "Perform table walk for addr 0x%lx", test_va);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100230
231 /* Last table level */
232 CHECK_EQUAL(expected_level, level);
233
234 /* tte index on the page */
235 CHECK_EQUAL(expected_idxs[i], index);
236
237 /* Expected tte attributes */
238 retval = xlat_test_helpers_get_attrs_for_va(ctx, test_va,
239 &attrs);
240
241 /* Return value */
242 CHECK_EQUAL(0, retval);
243
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100244 exp_upper_attrs = EXTRACT(UPPER_ATTRS, attrs);
245 upper_attrs = EXTRACT(UPPER_ATTRS, tte);
246 exp_lower_attrs = EXTRACT(LOWER_ATTRS, attrs);
247 if (is_feat_lpa2_4k_present() == true) {
248 lower_attrs = EXTRACT(LOWER_ATTRS,
249 (tte & ~TTE_OA_BITS_50_51_MASK));
250 } else {
251 lower_attrs = EXTRACT(LOWER_ATTRS, tte);
252 }
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100253
254 /* Validate that the attributes are as expected */
255 CHECK_VERBOSE((exp_upper_attrs == upper_attrs),
256 "Validate Upper Attrs: Read 0x%lx - Expected 0x%lx",
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100257 upper_attrs, exp_upper_attrs);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100258
259 CHECK_VERBOSE((exp_lower_attrs == lower_attrs),
260 "Validate Lower Attrs: Read 0x%lx - Expected 0x%lx",
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100261 lower_attrs, exp_lower_attrs);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100262
263 /* Validate the PA */
264 pa_mask = (1ULL << XLAT_ADDR_SHIFT(level)) - 1ULL;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100265 tte_oa = xlat_get_oa_from_tte(tte);
266
267 CHECK_EQUAL(tte_oa, (pa & ~pa_mask));
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100268
269 /* Validate the descriptor type */
270 type = (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC :
271 BLOCK_DESC;
272 CHECK_EQUAL(type, (tte & DESC_MASK));
273 }
274}
275
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100276void xlat_ctx_init_tc6(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100277{
278 struct xlat_ctx ctx;
279 struct xlat_ctx_cfg cfg;
280 struct xlat_ctx_tbls tbls;
281 uint64_t start_va;
282 size_t va_size, granularity;
283 unsigned int mmap_count;
284 xlat_addr_region_id_t va_region;
285 int retval;
286 struct xlat_mmap_region init_mmap[3U];
287 unsigned int tbl_idx[3U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100288 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100289
290 /**********************************************************************
291 * TEST CASE 6:
292 *
293 * For each possible base level, create a set of mmap regions
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100294 * ranging from level 1 or 0 (lowest level at which a valid walk can
295 * finish depending on whether FEAT_LPA2 is available) to
296 * XLAT_TABLE_LEVEL_MAX.
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100297 *
298 * For each possible (va_region, base_lvl, end_lvl) triplet for a
299 * base table there will be three mmap regions created:
300 *
301 * - First region mapped at the beginning of a table whose final
302 * lookup level is 'last_lvl'. This region will be descendant of
303 * an entry at the beginning of a 'base_lvl' table.
304 * - Second region mapped at a random index of a table whose final
305 * lookup level is 'last_lvl'. This region will be descendant of
306 * an entry at a random index of a 'base_lvl' table.
307 * - Third region mapped at the end of a table whose final
308 * lookup level is 'last_lvl'. This region will be descendant of
309 * an entry at the end of a 'base_lvl'.
310 *
311 * Then verify that the tables can be walked and that the levels,
312 * offsets and attributes on the ttes are as expected.
313 *
314 * This test validates that the xlat library is able to create
315 * tables starting on any valid initial lookup level and
316 * finishing on any valid level as well.
317 *********************************************************************/
318
319 mmap_count = 3U;
320
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100321 end_lvl = XLAT_MIN_BLOCK_LVL();
322 for (; end_lvl <= XLAT_TABLE_LEVEL_MAX; end_lvl++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100323 for (int i = 0U; i < VA_REGIONS; i++) {
324 va_region = (xlat_addr_region_id_t)i;
325
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100326 for (base_lvl = XLAT_TEST_MIN_LVL();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100327 base_lvl <= end_lvl;
328 base_lvl++) {
329
330 start_va = gen_va_space_params_by_lvl(base_lvl,
331 va_region,
332 &va_size);
333
334 retval = gen_mmap_array_by_level(&init_mmap[0U],
335 &tbl_idx[0U],
336 mmap_count,
337 base_lvl,
338 end_lvl,
339 &granularity,
340 start_va,
341 false);
342 /*
343 * verify that the test setup is correct so far
344 */
345 CHECK_TRUE(retval == 0);
346
347 /* Clean the data structures */
348 memset((void *)&ctx, 0,
349 sizeof(struct xlat_ctx));
350 memset((void *)&cfg, 0,
351 sizeof(struct xlat_ctx_cfg));
352 memset((void *)&tbls, 0,
353 sizeof(struct xlat_ctx_tbls));
354
355 /* Initialize the test structure */
356 retval = xlat_ctx_cfg_init(&cfg, va_region,
357 &init_mmap[0U],
358 mmap_count, va_size);
359
360 /*
361 * verify that the test setup is correct so far
362 */
363 CHECK_TRUE(retval == 0);
364
365 /* Test xlat_ctx_init() */
366 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
367 xlat_test_helpers_tbls(),
368 XLAT_TESTS_MAX_TABLES);
369
370 /*
371 * verify that the test setup is correct so far
372 */
373 CHECK_TRUE(retval == 0);
374
375 validate_xlat_tables(&ctx, &tbl_idx[0U],
376 end_lvl);
377 }
378 }
379 }
380}
381
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100382void xlat_get_llt_from_va_tc1(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100383{
384 struct xlat_ctx ctx;
385 struct xlat_ctx_cfg cfg;
386 struct xlat_ctx_tbls tbls;
387 struct xlat_llt_info tbl_info, tbl_val;
388 struct xlat_mmap_region init_mmap[3U];
389 uint64_t start_va;
390 size_t va_size, granularity;
391 unsigned int mmap_count, index;
392 xlat_addr_region_id_t va_region;
393 int retval;
394 unsigned int tbl_idx[3U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100395 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100396 unsigned int mmap_idx;
397 uint64_t tte;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100398 uint64_t test_va;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100399
400 /***************************************************************
401 * TEST CASE 1:
402 *
403 * For each possible base level, create a set of mmap regions
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100404 * ranging from level 1 or 0 (lowest level at which a valid walk
405 * can finish depending on whether FEAT_LPA2 is available) to
406 * XLAT_TABLE_LEVEL_MAX.
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100407 *
408 * For each possible (va_region, base_lvl, end_lvl) triplet,
409 * create 3 mappings that will correspond to a tte in the Last
410 * level Table. Then verify that the call to
411 * xlat_get_llt_from_va() is able to return the right
412 * xlat_tbl_info structure with the expected values.
413 ***************************************************************/
414
415 mmap_count = 3U;
416 va_region = (xlat_addr_region_id_t)test_helpers_get_rand_in_range(
417 0, VA_REGIONS - 1);
418
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100419 end_lvl = XLAT_MIN_BLOCK_LVL();
420 for (; end_lvl <= XLAT_TABLE_LEVEL_MAX; end_lvl++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100421
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100422 for (base_lvl = XLAT_TEST_MIN_LVL();
423 base_lvl <= end_lvl;
424 base_lvl++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100425
426 /* Clean the data structures */
427 memset((void *)&ctx, 0,
428 sizeof(struct xlat_ctx));
429 memset((void *)&cfg, 0,
430 sizeof(struct xlat_ctx_cfg));
431 memset((void *)&tbls, 0,
432 sizeof(struct xlat_ctx_tbls));
433 memset((void *)&tbl_info, 0,
434 sizeof(struct xlat_llt_info));
435 memset((void *)&tbl_val, 0,
436 sizeof(struct xlat_llt_info));
437
438 start_va = gen_va_space_params_by_lvl(base_lvl,
439 va_region,
440 &va_size);
441
442 /*
443 * Use gen_mmap_array_by_level() to generate
444 * the mmap array.
445 */
446 retval = gen_mmap_array_by_level(&init_mmap[0U],
447 &tbl_idx[0U],
448 mmap_count,
449 base_lvl,
450 end_lvl,
451 &granularity,
452 start_va,
453 true);
454
455 /* Ensure that so far the test setup is OK */
456 CHECK_TRUE(retval == 0);
457
458 retval = xlat_ctx_cfg_init(&cfg, va_region,
459 &init_mmap[0U],
460 mmap_count, va_size);
461
462 /* Ensure that so far the test setup is OK */
463 CHECK_TRUE(retval == 0);
464
465 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
466 xlat_test_helpers_tbls(),
467 XLAT_TESTS_MAX_TABLES);
468
469 /* Ensure that so far the test setup is OK */
470 CHECK_TRUE(retval == 0);
471
472 for (mmap_idx = 0U; mmap_idx < mmap_count; mmap_idx++) {
473 /*
474 * For each mmap region, pick up a
475 * random address for the test.
476 */
477 test_va = init_mmap[mmap_idx].base_va
478 + ctx.cfg->base_va;
479 test_va +=
480 test_helpers_get_rand_in_range(0,
481 init_mmap[mmap_idx].size - 1);
482
483 /*
484 * Perform a table walk to retrieve
485 * table info. Store the expected values
486 * inside the validation xlat_llt_info
487 * structure.
488 */
489 retval = xlat_test_helpers_table_walk(&ctx,
490 test_va,
491 &tte,
492 &(tbl_val.table),
493 &(tbl_val.level),
494 &index);
495
496 /*
497 * Calculate the expected base VA for the llt.
498 */
499 tbl_val.llt_base_va = start_va;
500 tbl_val.llt_base_va += (base_lvl < end_lvl) ?
501 (XLAT_BLOCK_SIZE(base_lvl) *
502 tbl_idx[mmap_idx]) : 0;
503
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100504 /* Ensure that so far the test setup is OK */
505 CHECK_TRUE(retval == 0);
506
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100507 VERBOSE("\nTesting VA 0x%lx", test_va);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100508
509 /* Test xlat_get_llt_from_va */
510 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
511 test_va);
512
513 /* Check the return value */
514 CHECK_TRUE(retval == 0);
515
516 /*
517 * Validate the structure returned by
518 * xlat_get_llt_from_va
519 */
520 MEMCMP_EQUAL((void *)&tbl_val,
521 (void *)&tbl_info,
522 sizeof(struct xlat_llt_info));
523 VERBOSE(" : PASS\n\n");
524 }
525 }
526 }
527}
528
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100529void xlat_get_llt_from_va_tc2(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100530{
531 struct xlat_ctx ctx;
532 struct xlat_ctx_cfg cfg;
533 struct xlat_ctx_tbls tbls;
534 struct xlat_llt_info tbl_info;
535 struct xlat_mmap_region init_mmap[3U];
536 unsigned int tbl_idx[3U];
537 size_t va_size, granularity;
538 uint64_t start_va, test_va;
539 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100540 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100541 int retval;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100542 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100543
544 /***************************************************************
545 * TEST CASE 2:
546 *
547 * Test xlat_get_llt_from_va() with a VAs ouside
548 * of the context VA space.
549 ***************************************************************/
550
551 /*
552 * Pick up a base and end levels for the translation tables.
553 * The leves are arbitrary. Just to have a VA space enough
554 * for the tests.
555 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100556 base_lvl = 2;
557 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100558
559 for (int i = 0U; i < VA_REGIONS; i++) {
560 va_region = (xlat_addr_region_id_t)i;
561
562 /*
563 * For the low region, the test will be executed
564 * only once, for a VA above the VA space limits.
565 *
566 * For the high region, the test will be executed twice:
567 * - Once for VA below the VA space.
568 * - Once of a VA above the VA space.
569 */
570 for (unsigned int j = 0; j < (i + 1U); j++) {
571
572 /* Clean the data structures */
573 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
574 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
575 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
576 memset((void *)&tbl_info, 0,
577 sizeof(struct xlat_llt_info));
578
579 /* Get VA space limits for Level 2 */
580 start_va = gen_va_space_params_by_lvl(base_lvl, va_region,
581 &va_size);
582
583 /*
584 * use gen_mmap_array_by_level() to generate
585 * the mmap for convenience.
586 */
587 retval = gen_mmap_array_by_level(&init_mmap[0U],
588 &tbl_idx[0U],
589 3U, base_lvl, end_lvl,
590 &granularity,
591 start_va,
592 true);
593
594 /* Ensure that so far the test setup is OK */
595 CHECK_TRUE(retval == 0);
596
597 retval = xlat_ctx_cfg_init(&cfg, va_region,
598 &init_mmap[0U], 3U,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100599 max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100600 CHECK_TRUE(retval == 0);
601
602 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
603 xlat_test_helpers_tbls(),
604 XLAT_TESTS_MAX_TABLES);
605 CHECK_TRUE(retval == 0);
606
607 VERBOSE("\n");
608
609 if (j == 0U) {
610 /*
611 * VA above the VA space.
612 * The upper range of the address is arbitrary.
613 */
614 test_va = (ctx.cfg->max_va_size) +
615 test_helpers_get_rand_in_range(0,
616 XLAT_BLOCK_SIZE(base_lvl) - 1);
617 } else {
618 /*
619 * VA below the VA space.
620 * The upper range of the address is arbitrary.
621 */
622 test_va = test_helpers_get_rand_in_range(0,
623 XLAT_BLOCK_SIZE(base_lvl) - 1);
624 }
625
626 /* Test xlat_get_llt_from_va */
627 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
628
629 /* Check the return value */
630 CHECK_VERBOSE((retval == -EFAULT),
631 "Testing VA 0x%lx", test_va);
632 VERBOSE("\n");
633 }
634 }
635}
636
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100637void xlat_get_llt_from_va_tc3(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100638{
639 struct xlat_ctx ctx;
640 struct xlat_ctx_cfg cfg;
641 struct xlat_ctx_tbls tbls;
642 struct xlat_llt_info tbl_info;
643 struct xlat_mmap_region init_mmap[3U];
644 unsigned int tbl_idx[3U];
645 size_t va_size, granularity;
646 uint64_t start_va, test_va;
647 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100648 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100649 int retval;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100650 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100651
652 /***************************************************************
653 * TEST CASE 3:
654 *
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100655 * Test xlat_get_llt_from_va() with an unmapped VA belonging to
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100656 * the context VA space.
657 ***************************************************************/
658
659 /*
660 * Pick up a base and end levels for the translation tables.
661 * The leves are arbitrary. Just to have a VA space enough
662 * for the tests.
663 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100664 base_lvl = XLAT_TEST_MIN_LVL();
665 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100666
667 for (int i = 0U; i < VA_REGIONS; i++) {
668 va_region = (xlat_addr_region_id_t)i;
669
670 /* Clean the data structures */
671 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
672 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
673 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
674 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
675
676 /* VA space boundaries */
677 start_va = gen_va_space_params_by_lvl(base_lvl, va_region,
678 &va_size);
679
680 /*
681 * use gen_mmap_array_by_level() to generate
682 * the mmap for convenience, although we will
683 * only use one of the mmap regions (init_mmap[0]).
684 */
685 retval = gen_mmap_array_by_level(&init_mmap[0U],
686 &tbl_idx[0U],
687 3U, base_lvl, end_lvl,
688 &granularity,
689 start_va,
690 true);
691
692 /* Ensure that so far the test setup is OK */
693 CHECK_TRUE(retval == 0);
694
695 retval = xlat_ctx_cfg_init(&cfg, va_region,
696 &init_mmap[0U], 3U,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100697 max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100698 CHECK_TRUE(retval == 0);
699
700 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
701 xlat_test_helpers_tbls(),
702 XLAT_TESTS_MAX_TABLES);
703 CHECK_TRUE(retval == 0);
704
705 VERBOSE("\n");
706
707 test_va = ctx.cfg->base_va;
708 test_va += (init_mmap[0U].base_va + init_mmap[0U].size);
709 test_va += test_helpers_get_rand_in_range(1, PAGE_SIZE - 1);
710
711 /* Test xlat_get_llt_from_va */
712 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
713
714 /* Check the return value */
715 CHECK_VERBOSE((retval == 0),
716 "Testing VA 0x%lx", test_va);
717 VERBOSE("\n");
718 }
719}
720
721void xlat_get_llt_from_va_prepare_assertion(struct xlat_ctx *ctx,
722 struct xlat_ctx_cfg *cfg,
723 struct xlat_ctx_tbls *tbls,
724 struct xlat_mmap_region *init_mmap)
725{
726 uint64_t start_va, end_va;
727 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100728 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100729
730 assert(ctx != NULL);
731 assert(cfg != NULL);
732 assert(tbls != NULL);
733 assert(init_mmap != NULL);
734
735 va_region = (xlat_addr_region_id_t)test_helpers_get_rand_in_range(0,
736 VA_REGIONS - 1U);
737
738 /* Clean the data structures */
739 memset((void *)ctx, 0, sizeof(struct xlat_ctx));
740 memset((void *)cfg, 0, sizeof(struct xlat_ctx_cfg));
741 memset((void *)tbls, 0, sizeof(struct xlat_ctx_tbls));
742
743 /* VA space boundaries */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100744 start_va = xlat_test_helpers_get_start_va(va_region, max_va_size);
745 end_va = start_va + max_va_size - 1ULL;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100746
747 /* Generate a random mmap area */
748 xlat_test_helpers_rand_mmap_array(init_mmap, 1U, start_va, end_va);
749
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100750 (void)xlat_ctx_cfg_init(cfg, va_region, init_mmap, 1U, max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100751
752 (void)xlat_ctx_init(ctx, cfg, tbls,
753 xlat_test_helpers_tbls(),
754 XLAT_TESTS_MAX_TABLES);
755}
756
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100757void xlat_get_llt_from_va_tc4(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100758{
759
760 struct xlat_ctx ctx;
761 struct xlat_ctx_cfg cfg;
762 struct xlat_ctx_tbls tbls;
763 struct xlat_mmap_region init_mmap;
764 uint64_t test_va;
765
766 /***************************************************************
767 * TEST CASE 4:
768 *
769 * Try calling xlat_get_llt_from_va() with a NULL
770 * xlat_llt_info structure
771 ***************************************************************/
772
773 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
774
775 test_va = ctx.cfg->base_va + init_mmap.base_va;
776
777 /* Test xlat_get_llt_from_va */
778 test_helpers_expect_assert_fail(true);
779 (void)xlat_get_llt_from_va(NULL, &ctx, test_va);
780 test_helpers_fail_if_no_assert_failed();
781}
782
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100783void xlat_get_llt_from_va_tc5(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100784{
785 struct xlat_llt_info tbl_info;
786
787 /***************************************************************
788 * TEST CASE 5:
789 *
790 * Try calling xlat_get_llt_from_va() with a NULL
791 * xlat_ctx structure.
792 ***************************************************************/
793
794 /* Clean the data structures */
795 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
796
797 /* Test xlat_get_llt_from_va: NULL xlat_ctx */
798 test_helpers_expect_assert_fail(true);
799 (void)xlat_get_llt_from_va(&tbl_info, NULL, 0ULL);
800 test_helpers_fail_if_no_assert_failed();
801}
802
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100803void xlat_get_llt_from_va_tc6(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100804{
805 struct xlat_ctx ctx;
806 struct xlat_ctx_cfg cfg;
807 struct xlat_ctx_tbls tbls;
808 struct xlat_llt_info tbl_info;
809 struct xlat_mmap_region init_mmap;
810 uint64_t test_va;
811
812 /***************************************************************
813 * TEST CASE 6:
814 *
815 * Try calling xlat_get_llt_from_va() with a NULL
816 * xlat_ctx_cfg structure.
817 ***************************************************************/
818
819 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
820 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
821
822 test_va = ctx.cfg->base_va + init_mmap.base_va;
823
824 /* Test xlat_get_llt_from_va: NULL xlat_ctx.cfg */
825 ctx.cfg = NULL;
826 test_helpers_expect_assert_fail(true);
827 (void)xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
828 test_helpers_fail_if_no_assert_failed();
829}
830
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100831void xlat_get_llt_from_va_tc7(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100832{
833 struct xlat_ctx ctx;
834 struct xlat_ctx_cfg cfg;
835 struct xlat_ctx_tbls tbls;
836 struct xlat_llt_info tbl_info;
837 struct xlat_mmap_region init_mmap;
838 uint64_t test_va;
839
840 /***************************************************************
841 * TEST CASE 7:
842 *
843 * Try calling xlat_get_llt_from_va() with a NULL
844 * xlat_ctx_tbls structure.
845 ***************************************************************/
846
847 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
848 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
849
850 test_va = ctx.cfg->base_va + init_mmap.base_va;
851
852 /* Test xlat_get_llt_from_va: NULL xlat_ctx.tbls */
853 ctx.tbls = NULL;
854 test_helpers_expect_assert_fail(true);
855 (void)xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
856 test_helpers_fail_if_no_assert_failed();
857}
858
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100859void xlat_get_llt_from_va_tc8(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100860{
861 struct xlat_ctx ctx;
862 struct xlat_ctx_cfg cfg;
863 struct xlat_ctx_tbls tbls;
864 struct xlat_llt_info tbl_info;
865 struct xlat_mmap_region init_mmap;
866 uint64_t test_va;
867
868 /***************************************************************
869 * TEST CASE 8:
870 *
871 * Try calling xlat_get_llt_from_va() with an uninitialized
872 * xlat_ctx_cfg structure.
873 * Perform a full initialization of the context and then force
874 * 'ctx.cfg->initialized' to 'false' so we can ensure that
875 * this is what it is actually tested.
876 ***************************************************************/
877
878 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
879 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
880
881 test_va = ctx.cfg->base_va + init_mmap.base_va;
882
883 /* Mark the cfg structure as not initialized */
884 cfg.initialized = false;
885
886 test_helpers_expect_assert_fail(true);
887 (void)xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
888 test_helpers_fail_if_no_assert_failed();
889}
890
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100891void xlat_get_llt_from_va_tc9(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100892{
893 struct xlat_ctx ctx;
894 struct xlat_ctx_cfg cfg;
895 struct xlat_ctx_tbls tbls;
896 struct xlat_llt_info tbl_info;
897 struct xlat_mmap_region init_mmap;
898 uint64_t test_va;
899
900 /***************************************************************
901 * TEST CASE 9:
902 *
903 * Try calling xlat_get_llt_from_va() with an uninitialized
904 * xlat_ctx_tbls structure.
905 * Perform a full initialization of the context and then force
906 * 'ctx.tbls->initialized' to 'false' so we can ensure that
907 * this is what it is actually tested.
908 ***************************************************************/
909
910 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
911 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
912
913 test_va = ctx.cfg->base_va + init_mmap.base_va;
914
915 /* Mark the tbls structure as not initialized */
916 tbls.initialized = false;
917
918 test_helpers_expect_assert_fail(true);
919 (void)xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
920 test_helpers_fail_if_no_assert_failed();
921}
922
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +0100923void xlat_get_tte_ptr_tc1(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100924{
925 struct xlat_ctx ctx;
926 struct xlat_ctx_cfg cfg;
927 struct xlat_ctx_tbls tbls;
928 struct xlat_llt_info tbl_info;
929 struct xlat_mmap_region init_mmap[3U];
930 unsigned int tbl_idx[3U];
931 uint64_t start_va, test_va;
932 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100933 unsigned int index;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100934 uint64_t *tte_ptr, *val_tte, *table;
935 uint64_t tte;
936 size_t granularity;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100937 int base_lvl, end_lvl;
938 int level, retval;
939 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100940
941 /***************************************************************
942 * TEST CASE 1:
943 *
944 * Initialize a translation context with a given VA space and
945 * 3 mmap regions at level 3. Then get a tte using
946 * xlat_get_tte_ptr() and verify that it is the correct entry.
947 *
948 * This test tries three different mmap areas per VA region:
949 *
Soby Mathewbddaba12023-04-22 03:34:00 +0000950 * - An address corresponding to the first entry at a
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100951 * last level table.
952 * - An address corresponding to the last entry at a
953 * last level table.
954 * - An address corresponding to an intermediate entry
955 * at a last level table.
956 *
Soby Mathewbddaba12023-04-22 03:34:00 +0000957 * The test also tests 2 negative cases :
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100958 * 1. It tries to get the TTE via xlat_get_tte() for a lower
959 * VA than the base VA.
960 * 2. It tries to get the TTE for a higher VA than is mapped
961 * by the last level table.
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100962 ***************************************************************/
963
964 /*
965 * Pick up a base and end levels for the translation tables.
966 * The leves are arbitrary. Just to have a VA space enough
967 * for the tests.
968 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100969 base_lvl = XLAT_TEST_MIN_LVL();
970 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100971
972 for (int i = 0U; i < VA_REGIONS; i++) {
973 va_region = (xlat_addr_region_id_t)i;
974
975 /* Clean the data structures */
976 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
977 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
978 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
979 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
980
981 /* VA space boundaries */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100982 start_va = xlat_test_helpers_get_start_va(va_region, max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100983
984 /* Generate the mmap regions */
985 retval = gen_mmap_array_by_level(&init_mmap[0U],
986 &tbl_idx[0U],
987 3U, base_lvl, end_lvl,
988 &granularity,
989 start_va, true);
990
991 /* Ensure that so far the test setup is OK */
992 CHECK_TRUE(retval == 0);
993
994 retval = xlat_ctx_cfg_init(&cfg, va_region, &init_mmap[0U], 3U,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +0100995 max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100996
997 /* Ensure that so far the test setup is OK */
998 CHECK_TRUE(retval == 0);
999
1000 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1001 xlat_test_helpers_tbls(),
1002 XLAT_TESTS_MAX_TABLES);
1003
1004 /* Ensure that so far the test setup is OK */
1005 CHECK_TRUE(retval == 0);
1006
1007 /* Get the xlat_llt_info structure used to look for TTEs */
1008 test_va = ctx.cfg->base_va + init_mmap[0].base_va;
1009 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1010
1011 /* Ensure that so far the test setup is OK */
1012 CHECK_TRUE(retval == 0);
1013
1014 /*
1015 * Iterate over test VAs of all 3 mmap regions to
1016 * test xlat_get_tte_ptr().
1017 */
1018 VERBOSE("\n");
1019 for (unsigned int i = 0U; i < 3U; i++) {
1020 /*
1021 * Get the xlat_llt_info structure used
1022 * to look for TTEs.
1023 */
1024 test_va = ctx.cfg->base_va + init_mmap[i].base_va;
1025 retval = xlat_get_llt_from_va(&tbl_info,
1026 &ctx, test_va);
1027
1028 /* Ensure that so far the test setup is OK */
1029 CHECK_TRUE(retval == 0);
1030
1031 /*
1032 * Add a random offset to the current 'test_va'
1033 * to be used for the tests.
1034 */
1035 test_va += test_helpers_get_rand_in_range(0,
1036 PAGE_SIZE - 1);
1037
1038 /*
1039 * Perform a table walk to get the table containing
1040 * the tte we are insterested in as well as the
1041 * index of that tte in the table.
1042 */
1043 retval = xlat_test_helpers_table_walk(&ctx, test_va,
1044 &tte, &table,
1045 &level, &index);
1046 /* Ensure that so far the test setup is OK */
1047 CHECK_TRUE(retval == 0);
1048
1049 /* Get a pointer to the expected tte */
1050 val_tte = &table[index];
1051
1052 /* Test xlat_get_tte_ptr() */
1053 tte_ptr = xlat_get_tte_ptr(&tbl_info, test_va);
1054
1055 /* Validate the output */
1056 CHECK_VERBOSE((val_tte == tte_ptr),
1057 "Testing VA 0x%lx", test_va);
1058 }
1059
1060 /*
1061 * test xlat_get_tte_ptr() agains a VA below the minimum
1062 * VA mapped by 'tbl_info'. Use init_mmap[1] for this test.
1063 */
1064 test_va = ctx.cfg->base_va + init_mmap[1U].base_va;
1065 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1066
1067 /* Ensure that so far the test setup is OK */
1068 CHECK_TRUE(retval == 0);
1069
1070 test_va = tbl_info.llt_base_va;
1071 test_va -= test_helpers_get_rand_in_range(1, PAGE_SIZE - 1);
1072
1073 tte_ptr = xlat_get_tte_ptr(&tbl_info, test_va);
1074
1075
1076 /* Validate the output */
1077 CHECK_VERBOSE((tte_ptr == NULL),
1078 "Check address 0x%lx against TT at VA 0x%lx",
1079 test_va, tbl_info.llt_base_va);
1080
Soby Mathewbddaba12023-04-22 03:34:00 +00001081 /*
1082 * test xlat_get_tte_ptr() against a VA above the max
1083 * VA mapped by 'tbl_info'. Use init_mmap[0] for this test.
1084 */
1085 test_va = ctx.cfg->base_va + init_mmap[0U].base_va;
1086 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1087
1088 /* Ensure that so far the test setup is OK */
1089 CHECK_TRUE(retval == 0);
1090
1091 test_va = tbl_info.llt_base_va + XLAT_BLOCK_SIZE(tbl_info.level - 1);
1092 test_va += test_helpers_get_rand_in_range(1, PAGE_SIZE - 1);
1093
1094 tte_ptr = xlat_get_tte_ptr(&tbl_info, test_va);
1095
1096 /* Validate the output */
1097 CHECK_VERBOSE((tte_ptr == NULL),
1098 "Check address 0x%lx against TT at VA 0x%lx",
1099 test_va, tbl_info.llt_base_va);
1100
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001101 VERBOSE("\n");
1102 }
1103}
1104
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001105void xlat_get_tte_ptr_tc2(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001106{
1107 /***************************************************************
1108 * TEST CASE 2:
1109 *
1110 * Try to get a tte using xlat_get_tte() with a NULL
1111 * xlat_llt_info structure.
1112 ***************************************************************/
1113
1114 test_helpers_expect_assert_fail(true);
1115 (void)xlat_get_tte_ptr(NULL, 0ULL);
1116 test_helpers_fail_if_no_assert_failed();
1117}
1118
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001119void xlat_get_tte_ptr_tc3(void)
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001120{
1121 struct xlat_ctx ctx;
1122 struct xlat_ctx_cfg cfg;
1123 struct xlat_ctx_tbls tbls;
1124 struct xlat_llt_info tbl_info;
1125 struct xlat_mmap_region init_mmap;
1126 uint64_t test_va;
1127
1128 /***************************************************************
1129 * TEST CASE 3:
1130 *
1131 * Try to get a tte using xlat_get_tte() in which 'level' is
1132 * below the minimum for the current architecture implementation.
1133 ***************************************************************/
1134
1135 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
1136 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
1137
1138 test_va = ctx.cfg->base_va + init_mmap.base_va;
1139
1140 /* Override the xlat_llt_info structure's level field */
1141 tbl_info.level = XLAT_TABLE_LEVEL_MIN - 1;
1142
1143 test_helpers_expect_assert_fail(true);
1144 (void)xlat_get_tte_ptr(&tbl_info, test_va);
1145 test_helpers_fail_if_no_assert_failed();
1146}
1147
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001148void xlat_get_tte_ptr_tc4(void)
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001149{
1150 struct xlat_ctx ctx;
1151 struct xlat_ctx_cfg cfg;
1152 struct xlat_ctx_tbls tbls;
1153 struct xlat_llt_info tbl_info;
1154 struct xlat_mmap_region init_mmap;
1155 uint64_t test_va;
1156
1157 /***************************************************************
1158 * TEST CASE 4:
1159 *
1160 * Try to get a tte using xlat_get_tte() in which 'level' is
1161 * above the maximum for the current architecture implementation.
1162 ***************************************************************/
1163
1164 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
1165 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
1166
1167 test_va = ctx.cfg->base_va + init_mmap.base_va;
1168
1169 /* Override the xlat_llt_info structure's level field */
1170 tbl_info.level = XLAT_TABLE_LEVEL_MAX + 1;
1171
1172 test_helpers_expect_assert_fail(true);
1173 (void)xlat_get_tte_ptr(&tbl_info, test_va);
1174 test_helpers_fail_if_no_assert_failed();
1175}
1176
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001177void xlat_unmap_memory_page_tc1(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001178{
1179 struct xlat_ctx ctx;
1180 struct xlat_ctx_cfg cfg;
1181 struct xlat_ctx_tbls tbls;
1182 uint64_t start_va;
1183 size_t va_size, granularity;
1184 unsigned int mmap_count;
1185 xlat_addr_region_id_t va_region;
1186 int retval;
1187 struct xlat_mmap_region init_mmap[3U];
1188 unsigned int tbl_idx[3U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001189 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001190
1191 /***************************************************************
1192 * TEST CASE 1:
1193 *
1194 * For each possible end lookup level, create a set transient
1195 * valid random mappings.
1196 *
1197 * For each possible (va_region, end_lvl) tuple, there will be
1198 * three mmap regions created:
1199 *
1200 * - First region mapped at the beginning of a table whose
1201 * final lookup level is 'end_lvl'
1202 * - Second region mapped at a random tte of a table whose
1203 * final lookup level is 'end_lvl'
1204 * - Third region mapped at the end of a table whose
1205 * final lookup level is 'end_lvl'
1206 *
1207 * Then verify that the tables can be unmapped and that the
1208 * resulting tte will contain a transient invalid entry.
1209 ***************************************************************/
1210
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001211 mmap_count = 3;
1212 base_lvl = XLAT_TEST_MIN_LVL();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001213
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001214 end_lvl = XLAT_MIN_BLOCK_LVL();
1215 for (; end_lvl <= XLAT_TABLE_LEVEL_MAX; end_lvl++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001216 for (int i = 0U; i < VA_REGIONS; i++) {
1217 va_region = (xlat_addr_region_id_t)i;
1218
1219 start_va = gen_va_space_params_by_lvl(base_lvl,
1220 va_region,
1221 &va_size);
1222
1223 retval = gen_mmap_array_by_level(&init_mmap[0U],
1224 &tbl_idx[0U],
1225 mmap_count,
1226 base_lvl,
1227 end_lvl,
1228 &granularity,
1229 start_va,
1230 false);
1231
1232 /* Verify that the test setup is correct so far */
1233 CHECK_TRUE(retval == 0);
1234
1235 /* Clean the data structures */
1236 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1237 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1238 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1239
1240 /* Initialize the test structure */
1241 retval = xlat_ctx_cfg_init(&cfg, va_region,
1242 &init_mmap[0U],
1243 mmap_count, va_size);
1244
1245 /* Verify that the test setup is correct so far */
1246 CHECK_TRUE(retval == 0);
1247
1248 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1249 xlat_test_helpers_tbls(),
1250 XLAT_TESTS_MAX_TABLES);
1251
1252 /* Verify that the test setup is correct so far */
1253 CHECK_TRUE(retval == 0);
1254
1255 /*
1256 * For each one of the mmap regions:
1257 * - get the TTE of a random VA and make it transient
1258 * - call xlat_unmap_memory_page() over the same VA
1259 * - verify that the TTE is now transient invalid.
1260 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001261 for (unsigned int j = 0U; j < mmap_count; j++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001262 uint64_t tte;
1263 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001264 unsigned int tte_idx;
1265 int tte_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001266 struct xlat_llt_info tbl_info;
1267 uint64_t offset =
1268 test_helpers_get_rand_in_range(0,
1269 PAGE_SIZE - 1);
1270 uint64_t test_va = init_mmap[j].base_va +
1271 ctx.cfg->base_va + offset;
1272
1273 /*
1274 * Perform a table walk to retrieve the table
1275 * where the VA is mapped along with the index
1276 * of the TTE within the table.
1277 */
1278 retval = xlat_test_helpers_table_walk(&ctx,
1279 test_va, &tte,
1280 &tbl_ptr, &tte_lvl,
1281 &tte_idx);
1282
1283 /*
1284 * Verify that the test setup is correct so far
1285 */
1286 CHECK_TRUE(retval == 0);
1287
1288 /*
1289 * The TTE is expected to be valid. Make it
1290 * transient valid within the table.
1291 */
1292 tbl_ptr[tte_idx] |=
1293 (1ULL << TRANSIENT_FLAG_SHIFT);
1294
1295 /*
1296 * Retrieve the xlat_llt_info structure needed
1297 * to feed xlat_unmap_memory_page()
1298 */
1299 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
1300 test_va);
1301
1302 /*
1303 * Verify that the test setup is correct so far
1304 */
1305 CHECK_TRUE(retval == 0);
1306
1307 /*
1308 * Try to unmap the page/block
1309 * containing `test_va`
1310 */
1311 retval = xlat_unmap_memory_page(&tbl_info,
1312 test_va);
1313
1314 /* Verify that the return is as expected */
1315 CHECK_TRUE(retval == 0);
1316
1317 /*
1318 * Verify that the TTE is marked as transient
1319 * invalid.
1320 */
1321 CHECK_VERBOSE((tbl_ptr[tte_idx] ==
1322 TRANSIENT_DESC),
1323 "Verifying TTE for VA 0x%lx is marked as Transient Invalid",
1324 test_va);
1325 }
1326 VERBOSE("\n");
1327 }
1328 }
1329}
1330
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001331void xlat_unmap_memory_page_tc2(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001332{
1333 struct xlat_ctx ctx;
1334 struct xlat_ctx_cfg cfg;
1335 struct xlat_ctx_tbls tbls;
1336 uint64_t start_va, test_va;
1337 size_t va_size, granularity;
1338 unsigned int mmap_count;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001339 unsigned int tte_idx;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001340 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001341 int retval, tte_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001342 struct xlat_mmap_region init_mmap[3U];
1343 unsigned int tbl_idx[3U];
1344 struct xlat_llt_info tbl_info;
1345 uint64_t tte, val_tte;
1346 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001347 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001348
1349 /***************************************************************
1350 * TEST CASE 2:
1351 *
1352 * Generate a mmap region with a set of transient valid
1353 * mappings. Then run a set of negative tests:
1354 *
1355 * - Try addresses below and above the range mapped by the
1356 * xlat_llt_info structure on a transient-valid entry.
1357 * - Try unmapping from a valid non-transient entry.
1358 * - Try unmapping from an invalid entry.
1359 ***************************************************************/
1360
1361 /*
1362 * Pick up a base and end levels for the translation tables.
1363 * The leves are arbitrary. Just to have a VA space enough
1364 * for the tests.
1365 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001366 base_lvl = XLAT_TEST_MIN_LVL();
1367 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001368
1369 mmap_count = 3U;
1370
1371 for (int i = 0U; i < VA_REGIONS; i++) {
1372 va_region = (xlat_addr_region_id_t)i;
1373
1374 start_va = gen_va_space_params_by_lvl(base_lvl,
1375 va_region, &va_size);
1376
1377 /*
1378 * We generate the mmap regions to use. We will be interested
1379 * in init_mmap[1].
1380 */
1381 retval = gen_mmap_array_by_level(&init_mmap[0U], &tbl_idx[0U],
1382 mmap_count, base_lvl, end_lvl,
1383 &granularity,
1384 start_va, false);
1385
1386 /* Verify that the test setup is correct so far */
1387 CHECK_TRUE(retval == 0);
1388
1389 /* Clean the data structures */
1390 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1391 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1392 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1393
1394 /* Initialize the test structure */
1395 retval = xlat_ctx_cfg_init(&cfg, va_region, &init_mmap[0U],
1396 mmap_count, va_size);
1397
1398 /* Verify that the test setup is correct so far */
1399 CHECK_TRUE(retval == 0);
1400
1401 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1402 xlat_test_helpers_tbls(),
1403 XLAT_TESTS_MAX_TABLES);
1404
1405 /* Verify that the test setup is correct so far */
1406 CHECK_TRUE(retval == 0);
1407
1408 /*
1409 * Make the TTEs of the mapped region, which is expected
1410 * to be valid, transient valid.
1411 */
1412 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1413
1414 /*
1415 * Perform a table walk to retrieve the table where the VA
1416 * is mapped along with the index of the TTE within the table.
1417 */
1418 retval = xlat_test_helpers_table_walk(&ctx, test_va, &tte,
1419 &tbl_ptr, &tte_lvl,
1420 &tte_idx);
1421
1422 /* Verify that the test setup is correct so far */
1423 CHECK_TRUE(retval == 0);
1424
1425 /*
1426 * The TTE is expected to be valid. Make it
1427 * transient valid within the table.
1428 */
1429 tbl_ptr[tte_idx] |= (1ULL << TRANSIENT_FLAG_SHIFT);
1430 val_tte = tbl_ptr[tte_idx];
1431
1432 /*
1433 * Retrieve the xlat_llt_info structure needed to feed
1434 * xlat_unmap_memory_page().
1435 */
1436 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
1437 init_mmap[1U].base_pa + ctx.cfg->base_va);
1438
1439 /* Verify that the test setup is correct so far */
1440 CHECK_TRUE(retval == 0);
1441
1442 /*
1443 * Test xlat_unmmap_memory_page() with a valid address
1444 * below the start of init_mmap[0U]. This gives us an address
1445 * below the range mapped by table we retrieved.
1446 */
1447 test_va = init_mmap[0U].base_va + ctx.cfg->base_va;
1448 test_va -= test_helpers_get_rand_in_range(1, PAGE_SIZE - 1);
1449
1450 /* Try to unmap the page/block containing `test_va` */
1451 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1452
1453 /* Verify that the return is as expected */
1454 CHECK_VERBOSE((retval == -EFAULT),
1455 "Testing VA 0x%lx on TTE for VA 0x%lx",
1456 test_va,
1457 init_mmap[1U].base_va + ctx.cfg->base_va);
1458
1459 /* Verify that the TTE remains unchanged */
1460 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1461
1462 /*
1463 * Repeat the process, this time with an address on a page
1464 * after the one mapped by init_mmap[2U]. This gives us an
1465 * address over the range mapped by table we retrieved.
1466 */
1467 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1468 test_va += PAGE_SIZE;
1469 test_va += test_helpers_get_rand_in_range(0,
1470 PAGE_SIZE - 1);
1471
1472 /* Try to unmap the page/block containing `test_va` */
1473 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1474
1475 /* Verify that the return is as expected */
1476 CHECK_VERBOSE((retval == -EFAULT),
1477 "Testing VA 0x%lx on TTE for VA 0x%lx",
1478 test_va,
1479 init_mmap[2U].base_va + ctx.cfg->base_va);
1480
1481 /* Verify that the TTE remains unchanged */
1482 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1483
1484 /*
1485 * Try to unmap an address marked as non-transient
1486 */
1487 tbl_ptr[tte_idx] &= ~(MASK(TRANSIENT_FLAG));
1488 val_tte = tbl_ptr[tte_idx];
1489
1490 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1491 test_va += test_helpers_get_rand_in_range(0, PAGE_SIZE - 1);
1492
1493 /* Try to unmap the page/block containing `test_va` */
1494 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1495
1496 /* Verify that the return is as expected */
1497 CHECK_VERBOSE((retval == -EFAULT),
1498 "Testing VA 0x%lx on a non-transient valid TTE",
1499 test_va);
1500
1501 /* Verify that the TTE remains unchanged */
1502 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1503
1504 /*
1505 * Try to unmap an address marked as invalid.
1506 */
1507 tbl_ptr[tte_idx] = INVALID_DESC;
1508 val_tte = tbl_ptr[tte_idx];
1509
1510 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1511 test_va += test_helpers_get_rand_in_range(0,
1512 PAGE_SIZE - 1);
1513
1514 /* Try to unmap the page/block containing `test_va` */
1515 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1516
1517 /* Verify that the return is as expected */
1518 CHECK_VERBOSE((retval == -EFAULT),
1519 "Testing VA 0x%lx on a ninvalid TTE",
1520 test_va);
1521
1522 /* Verify that the TTE remains unchanged */
1523 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1524 VERBOSE("\n");
1525 }
1526}
1527
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001528void xlat_unmap_memory_page_tc3(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001529{
1530 /***************************************************************
1531 * TEST CASE 3:
1532 *
1533 * Try calling xlat_unmap_memory_page with a NULL
1534 * xlat_llt_info structure.
1535 ***************************************************************/
1536
1537 test_helpers_expect_assert_fail(true);
1538 (void)xlat_unmap_memory_page(NULL, 0ULL);
1539 test_helpers_fail_if_no_assert_failed();
1540}
1541
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001542void xlat_map_memory_page_with_attrs_tc1(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001543{
1544 struct xlat_ctx ctx;
1545 struct xlat_ctx_cfg cfg;
1546 struct xlat_ctx_tbls tbls;
1547 uint64_t start_va;
1548 size_t va_size, granularity;
1549 unsigned int mmap_count;
1550 xlat_addr_region_id_t va_region;
1551 int retval;
1552 struct xlat_mmap_region init_mmap[3U];
1553 unsigned int tbl_idx[3U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001554 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001555
1556 /***************************************************************
1557 * TEST CASE 1:
1558 *
1559 * For each possible end lookup level, create a set transient
1560 * random mappings.
1561 *
1562 * For each possible (va_region, end_lvl) tuple, there will be three
1563 * mmap regions created:
1564 *
1565 * - First region mapped at the beginning of a table whose
1566 * final lookup level is 'end_lvl'
1567 * - Second region mapped at a random index of a table whose
1568 * final lookup level is 'end_lvl'
1569 * - Third region mapped at the end of a table whose
1570 * final lookup level is 'end_lvl'
1571 *
1572 * Then verify that we can map PA areas into the transient
1573 * entries using random attributes and that the generated
1574 * entry is valid.
1575 ***************************************************************/
1576
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001577 mmap_count = 3;
1578 base_lvl = XLAT_TEST_MIN_LVL();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001579
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001580 end_lvl = XLAT_MIN_BLOCK_LVL();
1581 for (; end_lvl <= XLAT_TABLE_LEVEL_MAX; end_lvl++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001582 for (int i = 0U; i < VA_REGIONS; i++) {
1583 va_region = (xlat_addr_region_id_t)i;
1584
1585 start_va = gen_va_space_params_by_lvl(base_lvl,
1586 va_region,
1587 &va_size);
1588
1589 retval = gen_mmap_array_by_level(&init_mmap[0U],
1590 &tbl_idx[0U],
1591 mmap_count,
1592 base_lvl,
1593 end_lvl,
1594 &granularity,
1595 start_va,
1596 false);
1597
1598 /* Verify that the test setup is correct so far */
1599 CHECK_TRUE(retval == 0);
1600
1601 /* Force all the mmap regions to be TRANSIENT */
1602 for (unsigned int j = 0U; j < mmap_count; j++) {
1603 init_mmap[j].attr = MT_TRANSIENT;
1604 }
1605
1606 /* Clean the data structures */
1607 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1608 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1609 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1610
1611 /* Initialize the test structure */
1612 retval = xlat_ctx_cfg_init(&cfg, va_region,
1613 &init_mmap[0U],
1614 mmap_count, va_size);
1615
1616 /* Verify that the test setup is correct so far */
1617 CHECK_TRUE(retval == 0);
1618
1619 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1620 xlat_test_helpers_tbls(),
1621 XLAT_TESTS_MAX_TABLES);
1622
1623 /* Verify that the test setup is correct so far */
1624 CHECK_TRUE(retval == 0);
1625
1626 /*
1627 * For each one of the mmap regions:
1628 * - Generate a random VA within the mmap VA space.
1629 * - generate a set of random attributes.
1630 * - Map a random PA to the generated VA and with
1631 * the generated attributes.
1632 * - call xlat_unmap_memory_page_map_with_attrs() to
1633 * create the mapping.
1634 * - verify that the new entry is valid.
1635 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001636 for (unsigned int j = 0U; j < mmap_count; j++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001637 uint64_t tte, val_tte, attrs, pa, type;
1638 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001639 unsigned int tte_idx;
1640 int tte_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001641 struct xlat_llt_info tbl_info;
1642 uint64_t offset =
1643 test_helpers_get_rand_in_range(0,
1644 init_mmap[i].size - 1);
1645 uint64_t test_va = init_mmap[j].base_va +
1646 ctx.cfg->base_va + offset;
1647
1648 /*
1649 * Perform a table walk to retrieve the table
1650 * where the VA is mapped along with the index
1651 * of the TTE within the table.
1652 */
1653 retval = xlat_test_helpers_table_walk(&ctx,
1654 test_va, &tte,
1655 &tbl_ptr, &tte_lvl,
1656 &tte_idx);
1657
1658 /*
1659 * Verify that the test setup is correct so far
1660 */
1661 CHECK_TRUE(retval == 0);
1662
1663 /* Generate a random set of attributes. */
1664 do {
1665 attrs = xlat_test_helpers_rand_mmap_attrs();
1666 } while (attrs == MT_TRANSIENT);
1667
1668 /*
1669 * Generate the validation TTE. For convenience,
1670 * create an identity mapping.
1671 */
1672 retval = xlat_test_helpers_gen_attrs(&val_tte,
1673 attrs);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001674 pa = init_mmap[j].base_va & XLAT_TEST_GET_PA_MASK();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001675
1676 /*
1677 * Add an arbitrary offset to PA to be passed to
1678 * xlat_map_memory_page_with_attrs()
1679 */
1680 pa += test_helpers_get_rand_in_range(1,
1681 XLAT_BLOCK_SIZE(end_lvl) - 1);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001682 val_tte |= set_oa_to_tte(pa &
1683 XLAT_ADDR_MASK(end_lvl));
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001684
1685 /* The TTE will be a transient one */
1686 val_tte |= (1ULL <<
1687 TRANSIENT_FLAG_SHIFT);
1688
1689 /* TTE type */
1690 type = (end_lvl == XLAT_TABLE_LEVEL_MAX) ?
1691 PAGE_DESC :
1692 BLOCK_DESC;
1693 val_tte |= type;
1694
1695 /* Verify the test setup */
1696 CHECK_TRUE(retval == 0);
1697
1698 /*
1699 * Retrieve the xlat_llt_info structure needed
1700 * to feed xlat_map_memory_page_with_attrs()
1701 */
1702 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
1703 test_va);
1704
1705 /*
1706 * Verify that the test setup is correct so far
1707 */
1708 CHECK_TRUE(retval == 0);
1709
1710 /*
1711 * Try to map the PA with the attributes to the
1712 * `test_va`
1713 */
1714 retval = xlat_map_memory_page_with_attrs(
1715 &tbl_info,
1716 test_va, pa, attrs);
1717
1718 /* Verify that the return is as expected */
1719 CHECK_VERBOSE((retval == 0),
1720 "Mapping PA 0x%.16lx to VA 0x%.16lx with attrs 0x%lx",
1721 pa, test_va, attrs);
1722 CHECK_TRUE(retval == 0);
1723
1724 /*
1725 * Verify that the generated TTE matches
1726 * the validation one.
1727 */
1728 CHECK_VERBOSE((val_tte == tbl_ptr[tte_idx]),
1729 "Verifying TTE 0x%.16lx against 0x%.16lx",
1730 tbl_ptr[tte_idx], val_tte);
1731 }
1732 VERBOSE("\n");
1733 }
1734 }
1735}
1736
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001737void xlat_map_memory_page_with_attrs_tc2(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001738{
1739 struct xlat_ctx ctx;
1740 struct xlat_ctx_cfg cfg;
1741 struct xlat_ctx_tbls tbls;
1742 uint64_t start_va, test_va, test_pa;
1743 size_t va_size, granularity;
1744 unsigned int mmap_count;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001745 unsigned int tte_idx;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001746 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001747 int tte_lvl, retval;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001748 struct xlat_mmap_region init_mmap[3U];
1749 unsigned int tbl_idx[3U];
1750 struct xlat_llt_info tbl_info;
1751 uint64_t tte, val_tte;
1752 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001753 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001754 unsigned int pa_range_bits_arr[] = {
1755 PARANGE_0000_WIDTH, PARANGE_0001_WIDTH, PARANGE_0010_WIDTH,
1756 PARANGE_0011_WIDTH, PARANGE_0100_WIDTH, PARANGE_0101_WIDTH,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001757 PARANGE_0110_WIDTH
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001758 };
1759 unsigned int parange_index = test_helpers_get_rand_in_range(0,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001760 ARRAY_SIZE(pa_range_bits_arr) - 1U);
1761 uint64_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001762
1763 /***************************************************************
1764 * TEST CASE 2:
1765 *
1766 * Generate a mmap region with a set of transient invalid
1767 * mappings. Then run a set of negative tests:
1768 *
1769 * - Try addresses below and above the range mapped by the
1770 * xlat_llt_info structure on a transient-invalid entry.
1771 * - Try mapping a PA lager than the maximum supported PA
1772 * to a transient-invalid entry.
1773 * - Try mapping to a transient-valid entry.
1774 * - Try mapping to a valid entry.
1775 * - Try mapping to an invalid entry.
1776 ***************************************************************/
1777
1778 /*
1779 * Pick up a base and end levels for the translation tables.
1780 * The leves are arbitrary. Just to have a VA space enough
1781 * for the tests.
1782 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001783 base_lvl = XLAT_TEST_MIN_LVL();
1784 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001785
1786 mmap_count = 3U;
1787
1788 for (int i = 0U; i < VA_REGIONS; i++) {
1789 va_region = (xlat_addr_region_id_t)i;
1790
1791 start_va = gen_va_space_params_by_lvl(base_lvl,
1792 va_region, &va_size);
1793
1794 /*
1795 * We generate the mmap regions to use. We will be interested
1796 * in init_mmap[1] for the transient-invalid tests and in
1797 * init_mmap[2] for the rest of tests.
1798 */
1799 retval = gen_mmap_array_by_level(&init_mmap[0U], &tbl_idx[0U],
1800 mmap_count, base_lvl, end_lvl,
1801 &granularity,
1802 start_va, false);
1803
1804 /* Verify that the test setup is correct so far */
1805 CHECK_TRUE(retval == 0);
1806
1807 /* Force init_mmap[1] to be TRANSIENT */
1808 init_mmap[1U].attr = MT_TRANSIENT;
1809
1810 /* Clean the data structures */
1811 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1812 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1813 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1814
1815 /* Initialize the test structure */
1816 retval = xlat_ctx_cfg_init(&cfg, va_region, &init_mmap[0U],
1817 mmap_count, va_size);
1818
1819 /* Verify that the test setup is correct so far */
1820 CHECK_TRUE(retval == 0);
1821
1822 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1823 xlat_test_helpers_tbls(),
1824 XLAT_TESTS_MAX_TABLES);
1825
1826 /* Verify that the test setup is correct so far */
1827 CHECK_TRUE(retval == 0);
1828
1829 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1830
1831 /*
1832 * Retrieve the xlat_llt_info structure needed to feed
1833 * xlat_map_memory_page_with_attrs().
1834 */
1835 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1836
1837 /* Verify that the test setup is correct so far */
1838 CHECK_TRUE(retval == 0);
1839
1840 /*
1841 * Test xlat_map_memory_page_with_attrs() with a valid address
1842 * within init_mmap[0]. This gives us an address
1843 * below the range mapped by table we retrieved (which belongs
1844 * to init_mmap[1]). For simplicity, set the attributes and
1845 * the PA both to 0x0.
1846 */
1847 test_va = init_mmap[0U].base_va + ctx.cfg->base_va;
Soby Mathewbddaba12023-04-22 03:34:00 +00001848 test_va += test_helpers_get_rand_in_range(0, init_mmap[0U].size - 1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001849
1850 /* Try to map to the page/block containing `test_va` */
1851 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1852 0ULL, 0ULL);
1853
1854 /* Verify that the return is as expected */
1855 CHECK_VERBOSE((retval == -EFAULT),
1856 "Testing VA 0x%.16lx on TTE for VA 0x%.16lx",
1857 test_va,
1858 init_mmap[1U].base_va + ctx.cfg->base_va);
1859
1860 /*
1861 * Repeat the process, this time with an address on a page
1862 * mapped by init_mmap[2]. This gives us an
1863 * address over the range mapped by table we retrieved.
1864 */
1865 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1866 test_va += test_helpers_get_rand_in_range(0,
1867 PAGE_SIZE - 1);
1868
1869 /* Try to map to the page/block containing `test_va` */
1870 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1871 0ULL, 0ULL);
1872
1873 /* Verify that the return is as expected */
1874 CHECK_VERBOSE((retval == -EFAULT),
1875 "Testing VA 0x%.16lx on TTE for VA 0x%.16lx",
1876 test_va,
1877 init_mmap[2U].base_va + ctx.cfg->base_va);
1878
1879 /*
1880 * Test with a PA larger than the maximum PA supported.
1881 */
1882
1883 /* Configure a random maximum PA supported */
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01001884 xlat_test_helpers_set_parange(parange_index);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001885 test_pa =
1886 (1ULL << pa_range_bits_arr[parange_index]) + PAGE_SIZE;
1887
1888 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1889
1890 /*
1891 * Perform a table walk to retrieve the table where the VA
1892 * is mapped along with the index of the TTE within the table.
1893 */
1894 retval = xlat_test_helpers_table_walk(&ctx, test_va, &tte,
1895 &tbl_ptr, &tte_lvl,
1896 &tte_idx);
1897
1898 /* Verify that the test setup is correct so far */
1899 CHECK_TRUE(retval == 0);
1900
1901 /*
1902 * Take a snapshot of the TTE. This will be used to verify
1903 * that the TTE hasn't been altered.
1904 */
1905 val_tte = tbl_ptr[tte_idx];
1906
1907 /* Get a random address to test */
1908 test_va += test_helpers_get_rand_in_range(0, PAGE_SIZE - 1);
1909
1910 /* Try to map the PA to the page/block containing `test_va` */
1911 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1912 test_pa, 0ULL);
1913
1914 /* Verify that the return is as expected */
1915 CHECK_VERBOSE((retval == -EFAULT),
1916 "Testing PA 0x%.16lx on with a max supported PA of 0x%.16llx",
1917 test_pa,
1918 (1ULL << pa_range_bits_arr[parange_index]) - 1ULL);
1919
1920 /* Verify that the TTE remains unchanged */
1921 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1922
1923 /* Restore the maximum supported PA size for next tests */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001924 host_write_sysreg("id_aa64mmfr0_el1", id_aa64mmfr0_el1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001925
1926 /* The rest of the tests will be based on init_mmap[2] */
1927 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1928
1929 /*
1930 * Perform a table walk to retrieve the table where the VA
1931 * is mapped along with the index of the TTE within the table.
1932 */
1933 retval = xlat_test_helpers_table_walk(&ctx, test_va, &tte,
1934 &tbl_ptr, &tte_lvl,
1935 &tte_idx);
1936
1937 /* Verify that the test setup is correct so far */
1938 CHECK_TRUE(retval == 0);
1939
1940 /*
Soby Mathewbddaba12023-04-22 03:34:00 +00001941 * Retrieve the xlat_llt_info structure needed to feed
1942 * xlat_map_memory_page_with_attrs().
1943 */
1944 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1945
1946 /* Verify that the test setup is correct so far */
1947 CHECK_TRUE(retval == 0);
1948
1949 /*
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001950 * Make the TTEs of the mapped region, which is expected
1951 * to be valid, transient valid.
1952 */
1953 tbl_ptr[tte_idx] |= (1ULL << TRANSIENT_FLAG_SHIFT);
1954
1955 /*
1956 * Take a snapshot of the TTE. This will be used to verify
1957 * that the TTE hasn't been altered.
1958 */
1959 val_tte = tbl_ptr[tte_idx];
1960
1961 /*
Soby Mathewbddaba12023-04-22 03:34:00 +00001962 * Now try to map a valid VA. In this case the associated
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001963 * TTE will contain a transient valid mapping.
1964 */
1965 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1966 test_va += test_helpers_get_rand_in_range(0, PAGE_SIZE - 1);
1967
1968 /* Try to map to the page/block containing `test_va` */
1969 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1970 0ULL, 0ULL);
1971
1972 /* Verify that the return is as expected */
1973 CHECK_VERBOSE((retval == -EFAULT),
1974 "Testing VA 0x%.16lx on a transient valid TTE",
1975 test_va);
1976
1977 /* Verify that the TTE remains unchanged */
1978 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1979
1980 /*
1981 * Repeat the last test but after clearing the TRANSIENT
1982 * flag from the TTE. This will test the behaviour with
1983 * a non transient TTE.
1984 */
1985 tbl_ptr[tte_idx] &= ~(1ULL << TRANSIENT_FLAG_SHIFT);
1986 val_tte = tbl_ptr[tte_idx];
1987
1988 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1989 test_va += test_helpers_get_rand_in_range(0, PAGE_SIZE - 1);
1990
1991 /* Try to map to the page/block containing `test_va` */
1992 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1993 0ULL, 0ULL);
1994
1995 /* Verify that the return is as expected */
1996 CHECK_VERBOSE((retval == -EFAULT),
1997 "Testing VA 0x%.16lx on a valid TTE",
1998 test_va);
1999
2000 /* Verify that the TTE remains unchanged */
2001 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
2002
2003 /*
2004 * Repeat the last test on an INVALID TTE.
2005 */
2006 tbl_ptr[tte_idx] = 0ULL;
2007 val_tte = 0ULL;
2008
2009 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
2010 test_va += test_helpers_get_rand_in_range(0,
2011 PAGE_SIZE - 1);
2012
2013 /* Try to map to the page/block containing `test_va` */
2014 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
2015 0ULL, 0ULL);
2016
2017 /* Verify that the return is as expected */
2018 CHECK_VERBOSE((retval == -EFAULT),
2019 "Testing VA 0x%.16lx on an invalid TTE",
2020 test_va);
2021
2022 /* Verify that the TTE remains unchanged */
2023 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
2024
2025 VERBOSE("\n");
2026 }
2027}
2028
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002029void xlat_map_memory_page_with_attrs_tc3(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002030{
2031 /***************************************************************
2032 * TEST CASE 3:
2033 *
2034 * Try calling xlat_map_memory_page_with_attrs with a NULL
2035 * xlat_llt_info structure.
2036 ***************************************************************/
2037
2038 test_helpers_expect_assert_fail(true);
2039 (void)xlat_map_memory_page_with_attrs(NULL, 0ULL, 0ULL, 0ULL);
2040 test_helpers_fail_if_no_assert_failed();
2041}
2042
2043/* Helper function to validate ttbrx_el2 registers */
2044static void validate_ttbrx_el2(struct xlat_ctx *ctx)
2045{
2046 uint64_t expected_ttbrx, ttbrx;
2047 xlat_addr_region_id_t va_region;
2048
2049 assert(ctx != NULL);
2050
2051 va_region = ctx->cfg->region;
2052
2053 /* BADDR */
2054 expected_ttbrx = ((uint64_t)&ctx->tbls->tables[0U]) &
2055 MASK(TTBRx_EL2_BADDR);
2056
2057 ttbrx = read_ttbr1_el2();
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002058 if (va_region == VA_LOW_REGION) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002059 ttbrx = read_ttbr0_el2();
2060
2061 /*
2062 * CnP bit. It is expected that the xlat library will
2063 * automatically set this bit for the low region.
2064 */
2065 expected_ttbrx |= (1ULL << TTBRx_EL2_CnP_SHIFT);
2066 }
2067
2068 CHECK_VERBOSE((expected_ttbrx == ttbrx),
2069 "Expected TTBR%c_EL2: 0x%lx - Received: 0x%lx",
2070 (unsigned int)va_region + '0',
2071 expected_ttbrx, ttbrx);
2072}
2073
2074/* Helper function to validate TCR_EL2 register */
2075static void validate_tcr_el2(struct xlat_ctx *low_ctx,
2076 struct xlat_ctx *high_ctx)
2077{
2078 uint64_t exp_tcr, tcr;
2079 size_t t0sz, t1sz;
2080 unsigned int parange;
2081
2082 tcr = read_tcr_el2();
2083
2084 /*
2085 * Calculate the VA space size for both contexts based on
2086 * the TCR_EL2 register.
2087 */
2088 t0sz = ((size_t)1) << (64U - EXTRACT(TCR_EL2_T0SZ, tcr));
2089 t1sz = ((size_t)1) << (64U - EXTRACT(TCR_EL2_T1SZ, tcr));
2090
2091 /* Validate the VA space size of the contexts */
2092 CHECK_VERBOSE((t0sz == low_ctx->cfg->max_va_size),
2093 "Check VA space size for Low Region: 0x%lx == 0x%lx",
2094 t0sz, low_ctx->cfg->max_va_size);
2095 CHECK_VERBOSE((t1sz == high_ctx->cfg->max_va_size),
2096 "Check VA space size for High Region: 0x%lx == 0x%lx",
2097 t1sz, high_ctx->cfg->max_va_size);
2098
2099 /* Mask out TxSZ fields. We have already validated them */
2100 tcr &= ~(MASK(TCR_EL2_T0SZ) | MASK(TCR_EL2_T1SZ));
2101
2102 /*
2103 * Inner and outher cacheability attributes as expected by RMM
2104 * for all the contexts.
2105 */
2106 exp_tcr = TCR_EL2_IRGN0_WBWA | TCR_EL2_ORGN0_WBWA;
2107 exp_tcr |= TCR_EL2_IRGN1_WBWA | TCR_EL2_ORGN1_WBWA;
2108
2109 /* Shareability as expected by RMM for all the contexts */
2110 exp_tcr |= TCR_EL2_SH0_IS | TCR_EL2_SH1_IS;
2111
2112 /* Granule size for all the contexts. Only 4KB supported */
2113 exp_tcr |= TCR_EL2_TG0_4K | TCR_EL2_TG1_4K;
2114
2115 /* Hierarchical permissions */
2116 exp_tcr |= TCR_EL2_AS | TCR_EL2_HPD0 | TCR_EL2_HPD1;
2117
2118 /*
2119 * Xlat library configures TCR_EL2.IPS to the max
2120 * supported by the PE.
2121 */
2122 parange = EXTRACT(ID_AA64MMFR0_EL1_PARANGE, read_id_aa64mmfr0_el1());
2123 exp_tcr |= INPLACE(TCR_EL2_IPS, parange);
2124
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002125 if (is_feat_lpa2_4k_present() == true) {
2126 exp_tcr |= (TCR_EL2_DS_LPA2_EN
2127 | TCR_EL2_SH0_IS
2128 | TCR_EL2_SH1_IS);
2129 }
2130
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002131 /* Validate tcr_el2*/
2132 CHECK_VERBOSE((exp_tcr == tcr),
2133 "Validate TCR_EL2 against expected value: Read 0x%.16lx - Expected 0x%.16lx",
2134 tcr, exp_tcr);
2135}
2136
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002137void xlat_arch_setup_mmu_cfg_tc1(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002138{
2139 struct xlat_ctx ctx[2U];
2140 struct xlat_ctx_cfg cfg[2U];
2141 struct xlat_ctx_tbls tbls[2U];
2142 uint64_t *base_tbl[2U], *xlat_tables;
2143 uint64_t start_va, end_va;
2144 xlat_addr_region_id_t va_region;
2145 int retval;
2146 struct xlat_mmap_region init_mmap[2U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002147 unsigned int pa_index, max_pa_index;
2148 bool lpa2 = is_feat_lpa2_4k_present();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002149 unsigned int pa_range_bits_arr[] = {
2150 PARANGE_0000_WIDTH, PARANGE_0001_WIDTH, PARANGE_0010_WIDTH,
2151 PARANGE_0011_WIDTH, PARANGE_0100_WIDTH, PARANGE_0101_WIDTH,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002152 PARANGE_0110_WIDTH
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002153 };
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002154 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002155
2156 /***************************************************************
2157 * TEST CASE 1:
2158 *
2159 * Generate a translation context for each region and configure
2160 * the MMU registers based on both contexts. Verify that the
2161 * right parameters have been configured.
2162 ***************************************************************/
2163
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002164 max_pa_index = ARRAY_SIZE(pa_range_bits_arr);
2165 max_pa_index = (lpa2 == true) ? max_pa_index : max_pa_index - 1U;
2166 pa_index = test_helpers_get_rand_in_range(0, max_pa_index - 1U);
2167
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002168 /* Clean the data structures */
2169 memset((void *)&ctx, 0, sizeof(struct xlat_ctx) * 2U);
2170 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg) * 2U);
2171 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls) * 2U);
2172
2173 /* Configure a random maximum PA supported */
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002174 xlat_test_helpers_set_parange(pa_index);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002175
2176 for (int i = 0U; i < VA_REGIONS; i++) {
2177 va_region = (xlat_addr_region_id_t)i;
2178
2179 xlat_tables = xlat_test_helpers_tbls();
2180 /* Use half of the available tables for each region */
2181 base_tbl[i] = &xlat_tables[(i * XLAT_TESTS_MAX_TABLES *
2182 XLAT_TABLE_ENTRIES) >> 1U];
2183 /* VA space boundaries */
2184 start_va = xlat_test_helpers_get_start_va(va_region,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002185 max_va_size);
2186 end_va = start_va + max_va_size - 1ULL;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002187
2188 /* Generate only a single mmap region for each region */
2189 xlat_test_helpers_rand_mmap_array(&init_mmap[i], 1U, start_va, end_va);
2190
2191 retval = xlat_ctx_cfg_init(&cfg[i], va_region, &init_mmap[i],
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002192 1U, max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002193 CHECK_TRUE(retval == 0);
2194
2195 retval = xlat_ctx_init(&ctx[i], &cfg[i], &tbls[i],
2196 base_tbl[i], XLAT_TESTS_MAX_TABLES >> 1U);
2197 CHECK_TRUE(retval == 0);
2198
2199 /* Initialize MMU for the given context */
2200 retval = xlat_arch_setup_mmu_cfg(&ctx[i]);
2201
2202 /* Verify that the MMU has been configured */
2203 CHECK_TRUE(retval == 0);
2204
2205 /* Validate TTBR_EL2 for each context */
2206 validate_ttbrx_el2(&ctx[i]);
2207 }
2208
2209 /* Validate TCR_EL2 for both contexts at the same time */
2210 validate_tcr_el2(&ctx[0U], &ctx[1U]);
2211}
2212
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002213void xlat_arch_setup_mmu_cfg_tc2(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002214{
2215 struct xlat_ctx ctx;
2216 struct xlat_ctx_cfg cfg;
2217 struct xlat_ctx_tbls tbls;
2218 uint64_t start_va, end_va;
2219 int retval;
2220 struct xlat_mmap_region init_mmap;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002221 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002222
2223 /***************************************************************
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002224 * TEST CASE 2:
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002225 *
2226 * Generate a valid translation context for one of the regions
2227 * and overwrite it to test different failure conditions on
2228 * xlat_arch_setup_mmu_cfg():
2229 *
2230 * - Call xlat_arch_setup_mmu_cfg() with the MMU enabled.
2231 * - Call xlat_arch_setup_mmu_cfg() with an uninitialized
2232 * context configuration.
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002233 * - Call xlat_arch_setup_mmu_cfg() for a CPU which
2234 * does not have support for 4KB granularity.
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002235 * - Call xlat_arch_setup_mmu_cfg() for a CPU which
2236 * does not support FEAT_LPA2 but reports a PA
2237 * size larger than 48 bits.
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002238 ***************************************************************/
2239
2240 /* Clean the data structures */
2241 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
2242 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
2243 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
2244
2245 /* VA space boundaries */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002246 start_va = xlat_test_helpers_get_start_va(VA_LOW_REGION, max_va_size);
2247 end_va = start_va + max_va_size - 1ULL;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002248
2249 /* Generate only a single mmap region for each region */
2250 xlat_test_helpers_rand_mmap_array(&init_mmap, 1U, start_va, end_va);
2251
2252 retval = xlat_ctx_cfg_init(&cfg, VA_LOW_REGION, &init_mmap,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002253 1U, max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002254 CHECK_TRUE(retval == 0);
2255
2256 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
2257 xlat_test_helpers_tbls(),
2258 XLAT_TESTS_MAX_TABLES);
2259 CHECK_TRUE(retval == 0);
2260
2261 /* Force the MMU enblement */
2262 xlat_enable_mmu_el2();
2263
2264 /* Try to initialize MMU for the given context */
2265 retval = xlat_arch_setup_mmu_cfg(&ctx);
2266
2267 /* Verify that the MMU has failed to be initialized */
2268 CHECK_TRUE(retval == -EPERM);
2269
2270 /* Restore SCTLR_EL2 to disable the MMU */
2271 write_sctlr_el2(0ULL);
2272
2273 /* Force the context to be uninitialized */
2274 ctx.cfg->initialized = false;
2275
2276 /* Try to initialize MMU for the given context */
2277 retval = xlat_arch_setup_mmu_cfg(&ctx);
2278
2279 /* Verify that the MMU has failed to be initialized */
2280 CHECK_TRUE(retval == -EINVAL);
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002281
2282 /* Restore the context initialized flag */
2283 ctx.cfg->initialized = true;
2284
2285 /* Force the architecture to report 4K granularity as not available */
2286 host_write_sysreg("id_aa64mmfr0_el1",
2287 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5U) |
2288 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2289 ID_AA64MMFR0_EL1_TGRAN4_NOT_SUPPORTED));
2290
2291 /* Try to initialize MMU for the given context */
2292 retval = xlat_arch_setup_mmu_cfg(&ctx);
2293
2294 /* Verify that the MMU has failed to be initialized */
2295 CHECK_TRUE(retval == -EPERM);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002296
2297 /*
2298 * Force the architecture to report 4K granularity available without
2299 * support for LPA2 but with an PA size of more than 48 bits.
2300 * Note that this scenario should never happen on the architecture
2301 * however, the library still checks for this.
2302 */
2303 host_write_sysreg("id_aa64mmfr0_el1",
2304 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 6U) |
2305 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2306 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED));
2307
2308 /* Try to initialize MMU for the given context */
2309 retval = xlat_arch_setup_mmu_cfg(&ctx);
2310
2311 /* Verify that the MMU has failed to be initialized */
2312 CHECK_TRUE(retval == -ENOMEM);
2313
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002314}
2315
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002316void xlat_arch_setup_mmu_cfg_tc3(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002317{
2318 /***************************************************************
2319 * TEST CASE 3:
2320 *
2321 * Test xlat_arch_setup_mmu_cfg() with a NULL context.
2322 ***************************************************************/
2323
2324 test_helpers_expect_assert_fail(true);
2325 (void)xlat_arch_setup_mmu_cfg(NULL);
2326 test_helpers_fail_if_no_assert_failed();
2327}
2328
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002329void xlat_arch_setup_mmu_cfg_tc4(void)
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002330{
2331 struct xlat_ctx ctx;
2332 struct xlat_ctx_cfg cfg;
2333 struct xlat_ctx_tbls tbls;
2334 struct xlat_mmap_region init_mmap;
2335
2336 /***************************************************************
2337 * TEST CASE 4:
2338 *
2339 * Test xlat_arch_setup_mmu_cfg() with a context in which the
2340 * configuration is NULL.
2341 *
2342 * This test reuses xlat_get_llt_from_va_prepare_assertion()
2343 * in order to generate an initial valid context.
2344 ***************************************************************/
2345
2346 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
2347
2348 /* Force the context configuration to NULL */
2349 ctx.cfg = NULL;
2350
2351 test_helpers_expect_assert_fail(true);
2352 (void)xlat_arch_setup_mmu_cfg(&ctx);
2353 test_helpers_fail_if_no_assert_failed();
2354}
2355
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002356void xlat_arch_setup_mmu_cfg_tc5(void)
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002357{
2358 struct xlat_ctx ctx;
2359 struct xlat_ctx_cfg cfg;
2360 struct xlat_ctx_tbls tbls;
2361 struct xlat_mmap_region init_mmap;
2362
2363 /***************************************************************
2364 * TEST CASE 5:
2365 *
2366 * Test xlat_arch_setup_mmu_cfg() with a context in which the
2367 * 'tbls' structure is NULL.
2368 *
2369 * This test reuses xlat_get_llt_from_va_prepare_assertion()
2370 * in order to generate an initial valid context.
2371 ***************************************************************/
2372
2373 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
2374
2375 /* Force the context tables structure to NULL */
2376 ctx.tbls = NULL;
2377
2378 test_helpers_expect_assert_fail(true);
2379 (void)xlat_arch_setup_mmu_cfg(&ctx);
2380 test_helpers_fail_if_no_assert_failed();
2381}
2382
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002383void xlat_get_oa_from_tte_tc1(void)
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002384{
2385 uint64_t test_tte, val_addr, output_addr;
2386
2387 /***************************************************************
2388 * TEST CASE 1:
2389 *
2390 * Test xlat_get_oa_from_tte() with 4K granularity and with and
2391 * without LPA2 support.
2392 ***************************************************************/
2393
2394 /*
2395 * Generate a random TTE to test. We are not concerned about the
2396 * validity of the TTE or about any bitfield that is not part of
2397 * the output address, as xlat_get_oa_from_tte() is expected to
2398 * just ignore those.
2399 */
2400 test_tte = ~0ULL;
2401
2402 /* Test with FEAT_LPA2 available */
2403 host_write_sysreg("id_aa64mmfr0_el1",
2404 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 6UL) |
2405 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2406 ID_AA64MMFR0_EL1_TGRAN4_LPA2));
2407
2408 /* Generate the validation address from the test TTE */
2409 val_addr = test_tte & BIT_MASK_ULL(TTE_OA_BIT_49_LPA2, OA_SHIFT);
2410 val_addr |= INPLACE(OA_BITS_50_51, EXTRACT(TTE_OA_BITS_50_51, test_tte));
2411
2412 output_addr = xlat_get_oa_from_tte(test_tte);
2413
2414 CHECK_VERBOSE((val_addr == output_addr),
2415 "Test xlat_get_oa_from_tte, LPA2 supported: OA = %p - Expected = %p",
2416 (void *)output_addr, (void *)val_addr);
2417
2418 /* Repeat the test, by disabling support for FEAT_LPA2 this time */
2419 host_write_sysreg("id_aa64mmfr0_el1",
2420 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5U) |
2421 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2422 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED));
2423
2424 /* Generate the validation address */
2425 val_addr = test_tte & BIT_MASK_ULL(TTE_OA_MSB, OA_SHIFT);
2426
2427 output_addr = xlat_get_oa_from_tte(test_tte);
2428
2429 CHECK_VERBOSE((val_addr == output_addr),
2430 "Test xlat_get_oa_from_tte, LPA2 not supported: OA = %p - Expected = %p",
2431 (void *)output_addr, (void *)val_addr);
2432}