blob: 8ec080d2c7eb4ed756140731e598b6ceb7063321 [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 */
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +0100156 tbl_idxs[1U] = (unsigned int)test_helpers_get_rand_in_range(2UL,
157 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 {
Mate Toth-Pal3f0a8ae2024-08-01 11:09:56 +0200163 attrs = xlat_test_helpers_rand_mmap_attrs(true);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100164 } 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;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +0100216 addr_offset = (unsigned int)test_helpers_get_rand_in_range(0UL,
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100217 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
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +0200276void xlat_ctx_init_tc5(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 /**********************************************************************
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +0200291 * TEST CASE 5:
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100292 *
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(
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +0100417 0UL, VA_REGIONS - 1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100418
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 +=
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +0100480 test_helpers_get_rand_in_range(0UL,
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100481 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) +
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +0100615 test_helpers_get_rand_in_range(0UL,
616 XLAT_BLOCK_SIZE(base_lvl) - 1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100617 } else {
618 /*
619 * VA below the VA space.
620 * The upper range of the address is arbitrary.
621 */
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +0100622 test_va = test_helpers_get_rand_in_range(0UL,
623 XLAT_BLOCK_SIZE(base_lvl) - 1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100624 }
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);
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +0100709 test_va += test_helpers_get_rand_in_range(1UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100710
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
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +0100735 va_region = (xlat_addr_region_id_t)test_helpers_get_rand_in_range(0UL,
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100736 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 */
Mate Toth-Pal3f0a8ae2024-08-01 11:09:56 +0200748 xlat_test_helpers_rand_mmap_array(init_mmap, 1U, start_va, end_va, true);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +0100749
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 */
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001035 test_va += test_helpers_get_rand_in_range(0UL,
1036 PAGE_SIZE - 1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001037
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;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001071 test_va -= test_helpers_get_rand_in_range(1UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001072
1073 tte_ptr = xlat_get_tte_ptr(&tbl_info, test_va);
1074
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001075 /* Validate the output */
1076 CHECK_VERBOSE((tte_ptr == NULL),
1077 "Check address 0x%lx against TT at VA 0x%lx",
1078 test_va, tbl_info.llt_base_va);
1079
Soby Mathewbddaba12023-04-22 03:34:00 +00001080 /*
1081 * test xlat_get_tte_ptr() against a VA above the max
1082 * VA mapped by 'tbl_info'. Use init_mmap[0] for this test.
1083 */
1084 test_va = ctx.cfg->base_va + init_mmap[0U].base_va;
1085 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1086
1087 /* Ensure that so far the test setup is OK */
1088 CHECK_TRUE(retval == 0);
1089
1090 test_va = tbl_info.llt_base_va + XLAT_BLOCK_SIZE(tbl_info.level - 1);
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001091 test_va += test_helpers_get_rand_in_range(1UL, PAGE_SIZE - 1UL);
Soby Mathewbddaba12023-04-22 03:34:00 +00001092
1093 tte_ptr = xlat_get_tte_ptr(&tbl_info, test_va);
1094
1095 /* Validate the output */
1096 CHECK_VERBOSE((tte_ptr == NULL),
1097 "Check address 0x%lx against TT at VA 0x%lx",
1098 test_va, tbl_info.llt_base_va);
1099
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001100 VERBOSE("\n");
1101 }
1102}
1103
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001104void xlat_get_tte_ptr_tc2(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001105{
1106 /***************************************************************
1107 * TEST CASE 2:
1108 *
1109 * Try to get a tte using xlat_get_tte() with a NULL
1110 * xlat_llt_info structure.
1111 ***************************************************************/
1112
1113 test_helpers_expect_assert_fail(true);
1114 (void)xlat_get_tte_ptr(NULL, 0ULL);
1115 test_helpers_fail_if_no_assert_failed();
1116}
1117
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001118void xlat_get_tte_ptr_tc3(void)
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001119{
1120 struct xlat_ctx ctx;
1121 struct xlat_ctx_cfg cfg;
1122 struct xlat_ctx_tbls tbls;
1123 struct xlat_llt_info tbl_info;
1124 struct xlat_mmap_region init_mmap;
1125 uint64_t test_va;
1126
1127 /***************************************************************
1128 * TEST CASE 3:
1129 *
1130 * Try to get a tte using xlat_get_tte() in which 'level' is
1131 * below the minimum for the current architecture implementation.
1132 ***************************************************************/
1133
1134 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
1135 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
1136
1137 test_va = ctx.cfg->base_va + init_mmap.base_va;
1138
1139 /* Override the xlat_llt_info structure's level field */
1140 tbl_info.level = XLAT_TABLE_LEVEL_MIN - 1;
1141
1142 test_helpers_expect_assert_fail(true);
1143 (void)xlat_get_tte_ptr(&tbl_info, test_va);
1144 test_helpers_fail_if_no_assert_failed();
1145}
1146
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001147void xlat_get_tte_ptr_tc4(void)
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001148{
1149 struct xlat_ctx ctx;
1150 struct xlat_ctx_cfg cfg;
1151 struct xlat_ctx_tbls tbls;
1152 struct xlat_llt_info tbl_info;
1153 struct xlat_mmap_region init_mmap;
1154 uint64_t test_va;
1155
1156 /***************************************************************
1157 * TEST CASE 4:
1158 *
1159 * Try to get a tte using xlat_get_tte() in which 'level' is
1160 * above the maximum for the current architecture implementation.
1161 ***************************************************************/
1162
1163 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
1164 memset((void *)&tbl_info, 0, sizeof(struct xlat_llt_info));
1165
1166 test_va = ctx.cfg->base_va + init_mmap.base_va;
1167
1168 /* Override the xlat_llt_info structure's level field */
1169 tbl_info.level = XLAT_TABLE_LEVEL_MAX + 1;
1170
1171 test_helpers_expect_assert_fail(true);
1172 (void)xlat_get_tte_ptr(&tbl_info, test_va);
1173 test_helpers_fail_if_no_assert_failed();
1174}
1175
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001176void xlat_unmap_memory_page_tc1(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001177{
1178 struct xlat_ctx ctx;
1179 struct xlat_ctx_cfg cfg;
1180 struct xlat_ctx_tbls tbls;
1181 uint64_t start_va;
1182 size_t va_size, granularity;
1183 unsigned int mmap_count;
1184 xlat_addr_region_id_t va_region;
1185 int retval;
1186 struct xlat_mmap_region init_mmap[3U];
1187 unsigned int tbl_idx[3U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001188 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001189
1190 /***************************************************************
1191 * TEST CASE 1:
1192 *
1193 * For each possible end lookup level, create a set transient
1194 * valid random mappings.
1195 *
1196 * For each possible (va_region, end_lvl) tuple, there will be
1197 * three mmap regions created:
1198 *
1199 * - First region mapped at the beginning of a table whose
1200 * final lookup level is 'end_lvl'
1201 * - Second region mapped at a random tte of a table whose
1202 * final lookup level is 'end_lvl'
1203 * - Third region mapped at the end of a table whose
1204 * final lookup level is 'end_lvl'
1205 *
1206 * Then verify that the tables can be unmapped and that the
1207 * resulting tte will contain a transient invalid entry.
1208 ***************************************************************/
1209
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001210 mmap_count = 3;
1211 base_lvl = XLAT_TEST_MIN_LVL();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001212
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001213 end_lvl = XLAT_MIN_BLOCK_LVL();
1214 for (; end_lvl <= XLAT_TABLE_LEVEL_MAX; end_lvl++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001215 for (int i = 0U; i < VA_REGIONS; i++) {
1216 va_region = (xlat_addr_region_id_t)i;
1217
1218 start_va = gen_va_space_params_by_lvl(base_lvl,
1219 va_region,
1220 &va_size);
1221
1222 retval = gen_mmap_array_by_level(&init_mmap[0U],
1223 &tbl_idx[0U],
1224 mmap_count,
1225 base_lvl,
1226 end_lvl,
1227 &granularity,
1228 start_va,
1229 false);
1230
1231 /* Verify that the test setup is correct so far */
1232 CHECK_TRUE(retval == 0);
1233
1234 /* Clean the data structures */
1235 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1236 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1237 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1238
1239 /* Initialize the test structure */
1240 retval = xlat_ctx_cfg_init(&cfg, va_region,
1241 &init_mmap[0U],
1242 mmap_count, va_size);
1243
1244 /* Verify that the test setup is correct so far */
1245 CHECK_TRUE(retval == 0);
1246
1247 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1248 xlat_test_helpers_tbls(),
1249 XLAT_TESTS_MAX_TABLES);
1250
1251 /* Verify that the test setup is correct so far */
1252 CHECK_TRUE(retval == 0);
1253
1254 /*
1255 * For each one of the mmap regions:
1256 * - get the TTE of a random VA and make it transient
1257 * - call xlat_unmap_memory_page() over the same VA
1258 * - verify that the TTE is now transient invalid.
1259 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001260 for (unsigned int j = 0U; j < mmap_count; j++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001261 uint64_t tte;
1262 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001263 unsigned int tte_idx;
1264 int tte_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001265 struct xlat_llt_info tbl_info;
1266 uint64_t offset =
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001267 test_helpers_get_rand_in_range(0UL,
1268 PAGE_SIZE - 1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001269 uint64_t test_va = init_mmap[j].base_va +
1270 ctx.cfg->base_va + offset;
1271
1272 /*
1273 * Perform a table walk to retrieve the table
1274 * where the VA is mapped along with the index
1275 * of the TTE within the table.
1276 */
1277 retval = xlat_test_helpers_table_walk(&ctx,
1278 test_va, &tte,
1279 &tbl_ptr, &tte_lvl,
1280 &tte_idx);
1281
1282 /*
1283 * Verify that the test setup is correct so far
1284 */
1285 CHECK_TRUE(retval == 0);
1286
1287 /*
1288 * The TTE is expected to be valid. Make it
1289 * transient valid within the table.
1290 */
1291 tbl_ptr[tte_idx] |=
1292 (1ULL << TRANSIENT_FLAG_SHIFT);
1293
1294 /*
1295 * Retrieve the xlat_llt_info structure needed
1296 * to feed xlat_unmap_memory_page()
1297 */
1298 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
1299 test_va);
1300
1301 /*
1302 * Verify that the test setup is correct so far
1303 */
1304 CHECK_TRUE(retval == 0);
1305
1306 /*
1307 * Try to unmap the page/block
1308 * containing `test_va`
1309 */
1310 retval = xlat_unmap_memory_page(&tbl_info,
1311 test_va);
1312
1313 /* Verify that the return is as expected */
1314 CHECK_TRUE(retval == 0);
1315
1316 /*
1317 * Verify that the TTE is marked as transient
1318 * invalid.
1319 */
1320 CHECK_VERBOSE((tbl_ptr[tte_idx] ==
1321 TRANSIENT_DESC),
1322 "Verifying TTE for VA 0x%lx is marked as Transient Invalid",
1323 test_va);
1324 }
1325 VERBOSE("\n");
1326 }
1327 }
1328}
1329
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001330void xlat_unmap_memory_page_tc2(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001331{
1332 struct xlat_ctx ctx;
1333 struct xlat_ctx_cfg cfg;
1334 struct xlat_ctx_tbls tbls;
1335 uint64_t start_va, test_va;
1336 size_t va_size, granularity;
1337 unsigned int mmap_count;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001338 unsigned int tte_idx;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001339 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001340 int retval, tte_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001341 struct xlat_mmap_region init_mmap[3U];
1342 unsigned int tbl_idx[3U];
1343 struct xlat_llt_info tbl_info;
1344 uint64_t tte, val_tte;
1345 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001346 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001347
1348 /***************************************************************
1349 * TEST CASE 2:
1350 *
1351 * Generate a mmap region with a set of transient valid
1352 * mappings. Then run a set of negative tests:
1353 *
1354 * - Try addresses below and above the range mapped by the
1355 * xlat_llt_info structure on a transient-valid entry.
1356 * - Try unmapping from a valid non-transient entry.
1357 * - Try unmapping from an invalid entry.
1358 ***************************************************************/
1359
1360 /*
1361 * Pick up a base and end levels for the translation tables.
1362 * The leves are arbitrary. Just to have a VA space enough
1363 * for the tests.
1364 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001365 base_lvl = XLAT_TEST_MIN_LVL();
1366 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001367
1368 mmap_count = 3U;
1369
1370 for (int i = 0U; i < VA_REGIONS; i++) {
1371 va_region = (xlat_addr_region_id_t)i;
1372
1373 start_va = gen_va_space_params_by_lvl(base_lvl,
1374 va_region, &va_size);
1375
1376 /*
1377 * We generate the mmap regions to use. We will be interested
1378 * in init_mmap[1].
1379 */
1380 retval = gen_mmap_array_by_level(&init_mmap[0U], &tbl_idx[0U],
1381 mmap_count, base_lvl, end_lvl,
1382 &granularity,
1383 start_va, false);
1384
1385 /* Verify that the test setup is correct so far */
1386 CHECK_TRUE(retval == 0);
1387
1388 /* Clean the data structures */
1389 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1390 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1391 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1392
1393 /* Initialize the test structure */
1394 retval = xlat_ctx_cfg_init(&cfg, va_region, &init_mmap[0U],
1395 mmap_count, va_size);
1396
1397 /* Verify that the test setup is correct so far */
1398 CHECK_TRUE(retval == 0);
1399
1400 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1401 xlat_test_helpers_tbls(),
1402 XLAT_TESTS_MAX_TABLES);
1403
1404 /* Verify that the test setup is correct so far */
1405 CHECK_TRUE(retval == 0);
1406
1407 /*
1408 * Make the TTEs of the mapped region, which is expected
1409 * to be valid, transient valid.
1410 */
1411 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1412
1413 /*
1414 * Perform a table walk to retrieve the table where the VA
1415 * is mapped along with the index of the TTE within the table.
1416 */
1417 retval = xlat_test_helpers_table_walk(&ctx, test_va, &tte,
1418 &tbl_ptr, &tte_lvl,
1419 &tte_idx);
1420
1421 /* Verify that the test setup is correct so far */
1422 CHECK_TRUE(retval == 0);
1423
1424 /*
1425 * The TTE is expected to be valid. Make it
1426 * transient valid within the table.
1427 */
1428 tbl_ptr[tte_idx] |= (1ULL << TRANSIENT_FLAG_SHIFT);
1429 val_tte = tbl_ptr[tte_idx];
1430
1431 /*
1432 * Retrieve the xlat_llt_info structure needed to feed
1433 * xlat_unmap_memory_page().
1434 */
1435 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
1436 init_mmap[1U].base_pa + ctx.cfg->base_va);
1437
1438 /* Verify that the test setup is correct so far */
1439 CHECK_TRUE(retval == 0);
1440
1441 /*
1442 * Test xlat_unmmap_memory_page() with a valid address
1443 * below the start of init_mmap[0U]. This gives us an address
1444 * below the range mapped by table we retrieved.
1445 */
1446 test_va = init_mmap[0U].base_va + ctx.cfg->base_va;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001447 test_va -= test_helpers_get_rand_in_range(1UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001448
1449 /* Try to unmap the page/block containing `test_va` */
1450 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1451
1452 /* Verify that the return is as expected */
1453 CHECK_VERBOSE((retval == -EFAULT),
1454 "Testing VA 0x%lx on TTE for VA 0x%lx",
1455 test_va,
1456 init_mmap[1U].base_va + ctx.cfg->base_va);
1457
1458 /* Verify that the TTE remains unchanged */
1459 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1460
1461 /*
1462 * Repeat the process, this time with an address on a page
1463 * after the one mapped by init_mmap[2U]. This gives us an
1464 * address over the range mapped by table we retrieved.
1465 */
1466 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1467 test_va += PAGE_SIZE;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001468 test_va += test_helpers_get_rand_in_range(0UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001469
1470 /* Try to unmap the page/block containing `test_va` */
1471 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1472
1473 /* Verify that the return is as expected */
1474 CHECK_VERBOSE((retval == -EFAULT),
1475 "Testing VA 0x%lx on TTE for VA 0x%lx",
1476 test_va,
1477 init_mmap[2U].base_va + ctx.cfg->base_va);
1478
1479 /* Verify that the TTE remains unchanged */
1480 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1481
1482 /*
1483 * Try to unmap an address marked as non-transient
1484 */
1485 tbl_ptr[tte_idx] &= ~(MASK(TRANSIENT_FLAG));
1486 val_tte = tbl_ptr[tte_idx];
1487
1488 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001489 test_va += test_helpers_get_rand_in_range(0UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001490
1491 /* Try to unmap the page/block containing `test_va` */
1492 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1493
1494 /* Verify that the return is as expected */
1495 CHECK_VERBOSE((retval == -EFAULT),
1496 "Testing VA 0x%lx on a non-transient valid TTE",
1497 test_va);
1498
1499 /* Verify that the TTE remains unchanged */
1500 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1501
1502 /*
1503 * Try to unmap an address marked as invalid.
1504 */
1505 tbl_ptr[tte_idx] = INVALID_DESC;
1506 val_tte = tbl_ptr[tte_idx];
1507
1508 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001509 test_va += test_helpers_get_rand_in_range(0UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001510
1511 /* Try to unmap the page/block containing `test_va` */
1512 retval = xlat_unmap_memory_page(&tbl_info, test_va);
1513
1514 /* Verify that the return is as expected */
1515 CHECK_VERBOSE((retval == -EFAULT),
1516 "Testing VA 0x%lx on a ninvalid TTE",
1517 test_va);
1518
1519 /* Verify that the TTE remains unchanged */
1520 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1521 VERBOSE("\n");
1522 }
1523}
1524
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001525void xlat_unmap_memory_page_tc3(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001526{
1527 /***************************************************************
1528 * TEST CASE 3:
1529 *
1530 * Try calling xlat_unmap_memory_page with a NULL
1531 * xlat_llt_info structure.
1532 ***************************************************************/
1533
1534 test_helpers_expect_assert_fail(true);
1535 (void)xlat_unmap_memory_page(NULL, 0ULL);
1536 test_helpers_fail_if_no_assert_failed();
1537}
1538
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001539void xlat_map_memory_page_with_attrs_tc1(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001540{
1541 struct xlat_ctx ctx;
1542 struct xlat_ctx_cfg cfg;
1543 struct xlat_ctx_tbls tbls;
1544 uint64_t start_va;
1545 size_t va_size, granularity;
1546 unsigned int mmap_count;
1547 xlat_addr_region_id_t va_region;
1548 int retval;
1549 struct xlat_mmap_region init_mmap[3U];
1550 unsigned int tbl_idx[3U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001551 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001552
1553 /***************************************************************
1554 * TEST CASE 1:
1555 *
1556 * For each possible end lookup level, create a set transient
1557 * random mappings.
1558 *
1559 * For each possible (va_region, end_lvl) tuple, there will be three
1560 * mmap regions created:
1561 *
1562 * - First region mapped at the beginning of a table whose
1563 * final lookup level is 'end_lvl'
1564 * - Second region mapped at a random index of a table whose
1565 * final lookup level is 'end_lvl'
1566 * - Third region mapped at the end of a table whose
1567 * final lookup level is 'end_lvl'
1568 *
1569 * Then verify that we can map PA areas into the transient
1570 * entries using random attributes and that the generated
1571 * entry is valid.
1572 ***************************************************************/
1573
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001574 mmap_count = 3;
1575 base_lvl = XLAT_TEST_MIN_LVL();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001576
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001577 end_lvl = XLAT_MIN_BLOCK_LVL();
1578 for (; end_lvl <= XLAT_TABLE_LEVEL_MAX; end_lvl++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001579 for (int i = 0U; i < VA_REGIONS; i++) {
1580 va_region = (xlat_addr_region_id_t)i;
1581
1582 start_va = gen_va_space_params_by_lvl(base_lvl,
1583 va_region,
1584 &va_size);
1585
1586 retval = gen_mmap_array_by_level(&init_mmap[0U],
1587 &tbl_idx[0U],
1588 mmap_count,
1589 base_lvl,
1590 end_lvl,
1591 &granularity,
1592 start_va,
1593 false);
1594
1595 /* Verify that the test setup is correct so far */
1596 CHECK_TRUE(retval == 0);
1597
1598 /* Force all the mmap regions to be TRANSIENT */
1599 for (unsigned int j = 0U; j < mmap_count; j++) {
1600 init_mmap[j].attr = MT_TRANSIENT;
1601 }
1602
1603 /* Clean the data structures */
1604 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1605 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1606 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1607
1608 /* Initialize the test structure */
1609 retval = xlat_ctx_cfg_init(&cfg, va_region,
1610 &init_mmap[0U],
1611 mmap_count, va_size);
1612
1613 /* Verify that the test setup is correct so far */
1614 CHECK_TRUE(retval == 0);
1615
1616 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1617 xlat_test_helpers_tbls(),
1618 XLAT_TESTS_MAX_TABLES);
1619
1620 /* Verify that the test setup is correct so far */
1621 CHECK_TRUE(retval == 0);
1622
1623 /*
1624 * For each one of the mmap regions:
1625 * - Generate a random VA within the mmap VA space.
1626 * - generate a set of random attributes.
1627 * - Map a random PA to the generated VA and with
1628 * the generated attributes.
1629 * - call xlat_unmap_memory_page_map_with_attrs() to
1630 * create the mapping.
1631 * - verify that the new entry is valid.
1632 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001633 for (unsigned int j = 0U; j < mmap_count; j++) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001634 uint64_t tte, val_tte, attrs, pa, type;
1635 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001636 unsigned int tte_idx;
1637 int tte_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001638 struct xlat_llt_info tbl_info;
1639 uint64_t offset =
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001640 test_helpers_get_rand_in_range(0UL,
1641 init_mmap[i].size - 1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001642 uint64_t test_va = init_mmap[j].base_va +
1643 ctx.cfg->base_va + offset;
1644
1645 /*
1646 * Perform a table walk to retrieve the table
1647 * where the VA is mapped along with the index
1648 * of the TTE within the table.
1649 */
1650 retval = xlat_test_helpers_table_walk(&ctx,
1651 test_va, &tte,
1652 &tbl_ptr, &tte_lvl,
1653 &tte_idx);
1654
1655 /*
1656 * Verify that the test setup is correct so far
1657 */
1658 CHECK_TRUE(retval == 0);
1659
1660 /* Generate a random set of attributes. */
1661 do {
Mate Toth-Pal3f0a8ae2024-08-01 11:09:56 +02001662 attrs = xlat_test_helpers_rand_mmap_attrs(true);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001663 } while (attrs == MT_TRANSIENT);
1664
1665 /*
1666 * Generate the validation TTE. For convenience,
1667 * create an identity mapping.
1668 */
1669 retval = xlat_test_helpers_gen_attrs(&val_tte,
1670 attrs);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001671 pa = init_mmap[j].base_va & XLAT_TEST_GET_PA_MASK();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001672
1673 /*
1674 * Add an arbitrary offset to PA to be passed to
1675 * xlat_map_memory_page_with_attrs()
1676 */
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001677 pa += test_helpers_get_rand_in_range(1UL,
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001678 XLAT_BLOCK_SIZE(end_lvl) - 1);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001679 val_tte |= set_oa_to_tte(pa &
1680 XLAT_ADDR_MASK(end_lvl));
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001681
1682 /* The TTE will be a transient one */
1683 val_tte |= (1ULL <<
1684 TRANSIENT_FLAG_SHIFT);
1685
1686 /* TTE type */
1687 type = (end_lvl == XLAT_TABLE_LEVEL_MAX) ?
1688 PAGE_DESC :
1689 BLOCK_DESC;
1690 val_tte |= type;
1691
1692 /* Verify the test setup */
1693 CHECK_TRUE(retval == 0);
1694
1695 /*
1696 * Retrieve the xlat_llt_info structure needed
1697 * to feed xlat_map_memory_page_with_attrs()
1698 */
1699 retval = xlat_get_llt_from_va(&tbl_info, &ctx,
1700 test_va);
1701
1702 /*
1703 * Verify that the test setup is correct so far
1704 */
1705 CHECK_TRUE(retval == 0);
1706
1707 /*
1708 * Try to map the PA with the attributes to the
1709 * `test_va`
1710 */
1711 retval = xlat_map_memory_page_with_attrs(
1712 &tbl_info,
1713 test_va, pa, attrs);
1714
1715 /* Verify that the return is as expected */
1716 CHECK_VERBOSE((retval == 0),
1717 "Mapping PA 0x%.16lx to VA 0x%.16lx with attrs 0x%lx",
1718 pa, test_va, attrs);
1719 CHECK_TRUE(retval == 0);
1720
1721 /*
1722 * Verify that the generated TTE matches
1723 * the validation one.
1724 */
1725 CHECK_VERBOSE((val_tte == tbl_ptr[tte_idx]),
1726 "Verifying TTE 0x%.16lx against 0x%.16lx",
1727 tbl_ptr[tte_idx], val_tte);
1728 }
1729 VERBOSE("\n");
1730 }
1731 }
1732}
1733
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01001734void xlat_map_memory_page_with_attrs_tc2(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001735{
1736 struct xlat_ctx ctx;
1737 struct xlat_ctx_cfg cfg;
1738 struct xlat_ctx_tbls tbls;
1739 uint64_t start_va, test_va, test_pa;
1740 size_t va_size, granularity;
1741 unsigned int mmap_count;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001742 unsigned int tte_idx;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001743 xlat_addr_region_id_t va_region;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001744 int tte_lvl, retval;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001745 struct xlat_mmap_region init_mmap[3U];
1746 unsigned int tbl_idx[3U];
1747 struct xlat_llt_info tbl_info;
1748 uint64_t tte, val_tte;
1749 uint64_t *tbl_ptr;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001750 int base_lvl, end_lvl;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001751 unsigned int pa_range_bits_arr[] = {
1752 PARANGE_0000_WIDTH, PARANGE_0001_WIDTH, PARANGE_0010_WIDTH,
1753 PARANGE_0011_WIDTH, PARANGE_0100_WIDTH, PARANGE_0101_WIDTH,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001754 PARANGE_0110_WIDTH
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001755 };
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001756 unsigned int parange_index =
1757 (unsigned int)test_helpers_get_rand_in_range(0UL,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001758 ARRAY_SIZE(pa_range_bits_arr) - 1U);
1759 uint64_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001760
1761 /***************************************************************
1762 * TEST CASE 2:
1763 *
1764 * Generate a mmap region with a set of transient invalid
1765 * mappings. Then run a set of negative tests:
1766 *
1767 * - Try addresses below and above the range mapped by the
1768 * xlat_llt_info structure on a transient-invalid entry.
1769 * - Try mapping a PA lager than the maximum supported PA
1770 * to a transient-invalid entry.
1771 * - Try mapping to a transient-valid entry.
1772 * - Try mapping to a valid entry.
1773 * - Try mapping to an invalid entry.
1774 ***************************************************************/
1775
1776 /*
1777 * Pick up a base and end levels for the translation tables.
1778 * The leves are arbitrary. Just to have a VA space enough
1779 * for the tests.
1780 */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001781 base_lvl = XLAT_TEST_MIN_LVL();
1782 end_lvl = 3;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001783
1784 mmap_count = 3U;
1785
1786 for (int i = 0U; i < VA_REGIONS; i++) {
1787 va_region = (xlat_addr_region_id_t)i;
1788
1789 start_va = gen_va_space_params_by_lvl(base_lvl,
1790 va_region, &va_size);
1791
1792 /*
1793 * We generate the mmap regions to use. We will be interested
1794 * in init_mmap[1] for the transient-invalid tests and in
1795 * init_mmap[2] for the rest of tests.
1796 */
1797 retval = gen_mmap_array_by_level(&init_mmap[0U], &tbl_idx[0U],
1798 mmap_count, base_lvl, end_lvl,
1799 &granularity,
1800 start_va, false);
1801
1802 /* Verify that the test setup is correct so far */
1803 CHECK_TRUE(retval == 0);
1804
1805 /* Force init_mmap[1] to be TRANSIENT */
1806 init_mmap[1U].attr = MT_TRANSIENT;
1807
1808 /* Clean the data structures */
1809 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
1810 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
1811 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
1812
1813 /* Initialize the test structure */
1814 retval = xlat_ctx_cfg_init(&cfg, va_region, &init_mmap[0U],
1815 mmap_count, va_size);
1816
1817 /* Verify that the test setup is correct so far */
1818 CHECK_TRUE(retval == 0);
1819
1820 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
1821 xlat_test_helpers_tbls(),
1822 XLAT_TESTS_MAX_TABLES);
1823
1824 /* Verify that the test setup is correct so far */
1825 CHECK_TRUE(retval == 0);
1826
1827 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1828
1829 /*
1830 * Retrieve the xlat_llt_info structure needed to feed
1831 * xlat_map_memory_page_with_attrs().
1832 */
1833 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1834
1835 /* Verify that the test setup is correct so far */
1836 CHECK_TRUE(retval == 0);
1837
1838 /*
1839 * Test xlat_map_memory_page_with_attrs() with a valid address
1840 * within init_mmap[0]. This gives us an address
1841 * below the range mapped by table we retrieved (which belongs
1842 * to init_mmap[1]). For simplicity, set the attributes and
1843 * the PA both to 0x0.
1844 */
1845 test_va = init_mmap[0U].base_va + ctx.cfg->base_va;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001846 test_va += test_helpers_get_rand_in_range(0UL,
1847 init_mmap[0U].size - 1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001848
1849 /* Try to map to the page/block containing `test_va` */
1850 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1851 0ULL, 0ULL);
1852
1853 /* Verify that the return is as expected */
1854 CHECK_VERBOSE((retval == -EFAULT),
1855 "Testing VA 0x%.16lx on TTE for VA 0x%.16lx",
1856 test_va,
1857 init_mmap[1U].base_va + ctx.cfg->base_va);
1858
1859 /*
1860 * Repeat the process, this time with an address on a page
1861 * mapped by init_mmap[2]. This gives us an
1862 * address over the range mapped by table we retrieved.
1863 */
1864 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001865 test_va += test_helpers_get_rand_in_range(0UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001866
1867 /* Try to map to the page/block containing `test_va` */
1868 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1869 0ULL, 0ULL);
1870
1871 /* Verify that the return is as expected */
1872 CHECK_VERBOSE((retval == -EFAULT),
1873 "Testing VA 0x%.16lx on TTE for VA 0x%.16lx",
1874 test_va,
1875 init_mmap[2U].base_va + ctx.cfg->base_va);
1876
1877 /*
1878 * Test with a PA larger than the maximum PA supported.
1879 */
1880
1881 /* Configure a random maximum PA supported */
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01001882 xlat_test_helpers_set_parange(parange_index);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001883 test_pa =
1884 (1ULL << pa_range_bits_arr[parange_index]) + PAGE_SIZE;
1885
1886 test_va = init_mmap[1U].base_va + ctx.cfg->base_va;
1887
1888 /*
1889 * Perform a table walk to retrieve the table where the VA
1890 * is mapped along with the index of the TTE within the table.
1891 */
1892 retval = xlat_test_helpers_table_walk(&ctx, test_va, &tte,
1893 &tbl_ptr, &tte_lvl,
1894 &tte_idx);
1895
1896 /* Verify that the test setup is correct so far */
1897 CHECK_TRUE(retval == 0);
1898
1899 /*
1900 * Take a snapshot of the TTE. This will be used to verify
1901 * that the TTE hasn't been altered.
1902 */
1903 val_tte = tbl_ptr[tte_idx];
1904
1905 /* Get a random address to test */
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001906 test_va += test_helpers_get_rand_in_range(0UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001907
1908 /* Try to map the PA to the page/block containing `test_va` */
1909 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1910 test_pa, 0ULL);
1911
1912 /* Verify that the return is as expected */
1913 CHECK_VERBOSE((retval == -EFAULT),
1914 "Testing PA 0x%.16lx on with a max supported PA of 0x%.16llx",
1915 test_pa,
1916 (1ULL << pa_range_bits_arr[parange_index]) - 1ULL);
1917
1918 /* Verify that the TTE remains unchanged */
1919 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1920
1921 /* Restore the maximum supported PA size for next tests */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01001922 host_write_sysreg("id_aa64mmfr0_el1", id_aa64mmfr0_el1);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001923
1924 /* The rest of the tests will be based on init_mmap[2] */
1925 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
1926
1927 /*
1928 * Perform a table walk to retrieve the table where the VA
1929 * is mapped along with the index of the TTE within the table.
1930 */
1931 retval = xlat_test_helpers_table_walk(&ctx, test_va, &tte,
1932 &tbl_ptr, &tte_lvl,
1933 &tte_idx);
1934
1935 /* Verify that the test setup is correct so far */
1936 CHECK_TRUE(retval == 0);
1937
1938 /*
Soby Mathewbddaba12023-04-22 03:34:00 +00001939 * Retrieve the xlat_llt_info structure needed to feed
1940 * xlat_map_memory_page_with_attrs().
1941 */
1942 retval = xlat_get_llt_from_va(&tbl_info, &ctx, test_va);
1943
1944 /* Verify that the test setup is correct so far */
1945 CHECK_TRUE(retval == 0);
1946
1947 /*
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001948 * Make the TTEs of the mapped region, which is expected
1949 * to be valid, transient valid.
1950 */
1951 tbl_ptr[tte_idx] |= (1ULL << TRANSIENT_FLAG_SHIFT);
1952
1953 /*
1954 * Take a snapshot of the TTE. This will be used to verify
1955 * that the TTE hasn't been altered.
1956 */
1957 val_tte = tbl_ptr[tte_idx];
1958
1959 /*
Soby Mathewbddaba12023-04-22 03:34:00 +00001960 * Now try to map a valid VA. In this case the associated
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001961 * TTE will contain a transient valid mapping.
1962 */
1963 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001964 test_va += test_helpers_get_rand_in_range(0UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001965
1966 /* Try to map to the page/block containing `test_va` */
1967 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1968 0ULL, 0ULL);
1969
1970 /* Verify that the return is as expected */
1971 CHECK_VERBOSE((retval == -EFAULT),
1972 "Testing VA 0x%.16lx on a transient valid TTE",
1973 test_va);
1974
1975 /* Verify that the TTE remains unchanged */
1976 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
1977
1978 /*
1979 * Repeat the last test but after clearing the TRANSIENT
1980 * flag from the TTE. This will test the behaviour with
1981 * a non transient TTE.
1982 */
1983 tbl_ptr[tte_idx] &= ~(1ULL << TRANSIENT_FLAG_SHIFT);
1984 val_tte = tbl_ptr[tte_idx];
1985
1986 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01001987 test_va += test_helpers_get_rand_in_range(0UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01001988
1989 /* Try to map to the page/block containing `test_va` */
1990 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
1991 0ULL, 0ULL);
1992
1993 /* Verify that the return is as expected */
1994 CHECK_VERBOSE((retval == -EFAULT),
1995 "Testing VA 0x%.16lx on a valid TTE",
1996 test_va);
1997
1998 /* Verify that the TTE remains unchanged */
1999 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
2000
2001 /*
2002 * Repeat the last test on an INVALID TTE.
2003 */
2004 tbl_ptr[tte_idx] = 0ULL;
2005 val_tte = 0ULL;
2006
2007 test_va = init_mmap[2U].base_va + ctx.cfg->base_va;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01002008 test_va += test_helpers_get_rand_in_range(0UL, PAGE_SIZE - 1UL);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002009
2010 /* Try to map to the page/block containing `test_va` */
2011 retval = xlat_map_memory_page_with_attrs(&tbl_info, test_va,
2012 0ULL, 0ULL);
2013
2014 /* Verify that the return is as expected */
2015 CHECK_VERBOSE((retval == -EFAULT),
2016 "Testing VA 0x%.16lx on an invalid TTE",
2017 test_va);
2018
2019 /* Verify that the TTE remains unchanged */
2020 CHECK_EQUAL(val_tte, tbl_ptr[tte_idx]);
2021
2022 VERBOSE("\n");
2023 }
2024}
2025
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002026void xlat_map_memory_page_with_attrs_tc3(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002027{
2028 /***************************************************************
2029 * TEST CASE 3:
2030 *
2031 * Try calling xlat_map_memory_page_with_attrs with a NULL
2032 * xlat_llt_info structure.
2033 ***************************************************************/
2034
2035 test_helpers_expect_assert_fail(true);
2036 (void)xlat_map_memory_page_with_attrs(NULL, 0ULL, 0ULL, 0ULL);
2037 test_helpers_fail_if_no_assert_failed();
2038}
2039
2040/* Helper function to validate ttbrx_el2 registers */
2041static void validate_ttbrx_el2(struct xlat_ctx *ctx)
2042{
2043 uint64_t expected_ttbrx, ttbrx;
2044 xlat_addr_region_id_t va_region;
2045
2046 assert(ctx != NULL);
2047
2048 va_region = ctx->cfg->region;
2049
2050 /* BADDR */
2051 expected_ttbrx = ((uint64_t)&ctx->tbls->tables[0U]) &
2052 MASK(TTBRx_EL2_BADDR);
2053
2054 ttbrx = read_ttbr1_el2();
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002055 if (va_region == VA_LOW_REGION) {
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002056 ttbrx = read_ttbr0_el2();
2057
2058 /*
2059 * CnP bit. It is expected that the xlat library will
2060 * automatically set this bit for the low region.
2061 */
2062 expected_ttbrx |= (1ULL << TTBRx_EL2_CnP_SHIFT);
2063 }
2064
2065 CHECK_VERBOSE((expected_ttbrx == ttbrx),
2066 "Expected TTBR%c_EL2: 0x%lx - Received: 0x%lx",
2067 (unsigned int)va_region + '0',
2068 expected_ttbrx, ttbrx);
2069}
2070
2071/* Helper function to validate TCR_EL2 register */
2072static void validate_tcr_el2(struct xlat_ctx *low_ctx,
2073 struct xlat_ctx *high_ctx)
2074{
2075 uint64_t exp_tcr, tcr;
2076 size_t t0sz, t1sz;
2077 unsigned int parange;
2078
2079 tcr = read_tcr_el2();
2080
2081 /*
2082 * Calculate the VA space size for both contexts based on
2083 * the TCR_EL2 register.
2084 */
2085 t0sz = ((size_t)1) << (64U - EXTRACT(TCR_EL2_T0SZ, tcr));
2086 t1sz = ((size_t)1) << (64U - EXTRACT(TCR_EL2_T1SZ, tcr));
2087
2088 /* Validate the VA space size of the contexts */
2089 CHECK_VERBOSE((t0sz == low_ctx->cfg->max_va_size),
2090 "Check VA space size for Low Region: 0x%lx == 0x%lx",
2091 t0sz, low_ctx->cfg->max_va_size);
2092 CHECK_VERBOSE((t1sz == high_ctx->cfg->max_va_size),
2093 "Check VA space size for High Region: 0x%lx == 0x%lx",
2094 t1sz, high_ctx->cfg->max_va_size);
2095
2096 /* Mask out TxSZ fields. We have already validated them */
2097 tcr &= ~(MASK(TCR_EL2_T0SZ) | MASK(TCR_EL2_T1SZ));
2098
2099 /*
2100 * Inner and outher cacheability attributes as expected by RMM
2101 * for all the contexts.
2102 */
2103 exp_tcr = TCR_EL2_IRGN0_WBWA | TCR_EL2_ORGN0_WBWA;
2104 exp_tcr |= TCR_EL2_IRGN1_WBWA | TCR_EL2_ORGN1_WBWA;
2105
2106 /* Shareability as expected by RMM for all the contexts */
2107 exp_tcr |= TCR_EL2_SH0_IS | TCR_EL2_SH1_IS;
2108
2109 /* Granule size for all the contexts. Only 4KB supported */
2110 exp_tcr |= TCR_EL2_TG0_4K | TCR_EL2_TG1_4K;
2111
2112 /* Hierarchical permissions */
2113 exp_tcr |= TCR_EL2_AS | TCR_EL2_HPD0 | TCR_EL2_HPD1;
2114
2115 /*
2116 * Xlat library configures TCR_EL2.IPS to the max
2117 * supported by the PE.
2118 */
2119 parange = EXTRACT(ID_AA64MMFR0_EL1_PARANGE, read_id_aa64mmfr0_el1());
2120 exp_tcr |= INPLACE(TCR_EL2_IPS, parange);
2121
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002122 if (is_feat_lpa2_4k_present() == true) {
2123 exp_tcr |= (TCR_EL2_DS_LPA2_EN
2124 | TCR_EL2_SH0_IS
2125 | TCR_EL2_SH1_IS);
2126 }
2127
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002128 /* Validate tcr_el2*/
2129 CHECK_VERBOSE((exp_tcr == tcr),
2130 "Validate TCR_EL2 against expected value: Read 0x%.16lx - Expected 0x%.16lx",
2131 tcr, exp_tcr);
2132}
2133
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002134void xlat_arch_setup_mmu_cfg_tc1(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002135{
2136 struct xlat_ctx ctx[2U];
2137 struct xlat_ctx_cfg cfg[2U];
2138 struct xlat_ctx_tbls tbls[2U];
2139 uint64_t *base_tbl[2U], *xlat_tables;
2140 uint64_t start_va, end_va;
2141 xlat_addr_region_id_t va_region;
2142 int retval;
2143 struct xlat_mmap_region init_mmap[2U];
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002144 unsigned int pa_index, max_pa_index;
2145 bool lpa2 = is_feat_lpa2_4k_present();
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002146 unsigned int pa_range_bits_arr[] = {
2147 PARANGE_0000_WIDTH, PARANGE_0001_WIDTH, PARANGE_0010_WIDTH,
2148 PARANGE_0011_WIDTH, PARANGE_0100_WIDTH, PARANGE_0101_WIDTH,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002149 PARANGE_0110_WIDTH
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002150 };
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002151 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002152 struct xlat_mmu_cfg mmu_config;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002153
2154 /***************************************************************
2155 * TEST CASE 1:
2156 *
2157 * Generate a translation context for each region and configure
2158 * the MMU registers based on both contexts. Verify that the
2159 * right parameters have been configured.
2160 ***************************************************************/
2161
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002162 max_pa_index = ARRAY_SIZE(pa_range_bits_arr);
2163 max_pa_index = (lpa2 == true) ? max_pa_index : max_pa_index - 1U;
Javier Almansa Sobrinoe627b4d2023-10-12 11:25:08 +01002164 pa_index = (unsigned int)test_helpers_get_rand_in_range(0UL,
2165 max_pa_index - 1U);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002166
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002167 /* Clean the data structures */
2168 memset((void *)&ctx, 0, sizeof(struct xlat_ctx) * 2U);
2169 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg) * 2U);
2170 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls) * 2U);
2171
2172 /* Configure a random maximum PA supported */
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002173 xlat_test_helpers_set_parange(pa_index);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002174
2175 for (int i = 0U; i < VA_REGIONS; i++) {
2176 va_region = (xlat_addr_region_id_t)i;
2177
2178 xlat_tables = xlat_test_helpers_tbls();
2179 /* Use half of the available tables for each region */
2180 base_tbl[i] = &xlat_tables[(i * XLAT_TESTS_MAX_TABLES *
2181 XLAT_TABLE_ENTRIES) >> 1U];
2182 /* VA space boundaries */
2183 start_va = xlat_test_helpers_get_start_va(va_region,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002184 max_va_size);
2185 end_va = start_va + max_va_size - 1ULL;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002186
2187 /* Generate only a single mmap region for each region */
Mate Toth-Pal3f0a8ae2024-08-01 11:09:56 +02002188 xlat_test_helpers_rand_mmap_array(&init_mmap[i], 1U, start_va, end_va, true);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002189
2190 retval = xlat_ctx_cfg_init(&cfg[i], va_region, &init_mmap[i],
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002191 1U, max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002192 CHECK_TRUE(retval == 0);
2193
2194 retval = xlat_ctx_init(&ctx[i], &cfg[i], &tbls[i],
2195 base_tbl[i], XLAT_TESTS_MAX_TABLES >> 1U);
2196 CHECK_TRUE(retval == 0);
2197
2198 /* Initialize MMU for the given context */
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002199 retval = xlat_arch_setup_mmu_cfg(&ctx[i], &mmu_config);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002200
2201 /* Verify that the MMU has been configured */
2202 CHECK_TRUE(retval == 0);
2203
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002204 /* Write the MMU config for the given context */
2205 xlat_arch_write_mmu_cfg(&mmu_config);
2206
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002207 /* Validate TTBR_EL2 for each context */
2208 validate_ttbrx_el2(&ctx[i]);
2209 }
2210
2211 /* Validate TCR_EL2 for both contexts at the same time */
2212 validate_tcr_el2(&ctx[0U], &ctx[1U]);
2213}
2214
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002215void xlat_arch_setup_mmu_cfg_tc2(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002216{
2217 struct xlat_ctx ctx;
2218 struct xlat_ctx_cfg cfg;
2219 struct xlat_ctx_tbls tbls;
2220 uint64_t start_va, end_va;
2221 int retval;
2222 struct xlat_mmap_region init_mmap;
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002223 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002224 struct xlat_mmu_cfg mmu_config;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002225
2226 /***************************************************************
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002227 * TEST CASE 2:
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002228 *
2229 * Generate a valid translation context for one of the regions
2230 * and overwrite it to test different failure conditions on
2231 * xlat_arch_setup_mmu_cfg():
2232 *
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002233 * - Call xlat_arch_setup_mmu_cfg() with an uninitialized
2234 * context configuration.
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002235 * - Call xlat_arch_setup_mmu_cfg() for a CPU which
2236 * does not have support for 4KB granularity.
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002237 * - Call xlat_arch_setup_mmu_cfg() for a CPU which
2238 * does not support FEAT_LPA2 but reports a PA
2239 * size larger than 48 bits.
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002240 ***************************************************************/
2241
2242 /* Clean the data structures */
2243 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
2244 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
2245 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
2246
2247 /* VA space boundaries */
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002248 start_va = xlat_test_helpers_get_start_va(VA_LOW_REGION, max_va_size);
2249 end_va = start_va + max_va_size - 1ULL;
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002250
2251 /* Generate only a single mmap region for each region */
Mate Toth-Pal3f0a8ae2024-08-01 11:09:56 +02002252 xlat_test_helpers_rand_mmap_array(&init_mmap, 1U, start_va, end_va, true);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002253
2254 retval = xlat_ctx_cfg_init(&cfg, VA_LOW_REGION, &init_mmap,
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002255 1U, max_va_size);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002256 CHECK_TRUE(retval == 0);
2257
2258 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
2259 xlat_test_helpers_tbls(),
2260 XLAT_TESTS_MAX_TABLES);
2261 CHECK_TRUE(retval == 0);
2262
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002263 /* Force the context to be uninitialized */
2264 ctx.cfg->initialized = false;
2265
2266 /* Try to initialize MMU for the given context */
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002267 retval = xlat_arch_setup_mmu_cfg(&ctx, &mmu_config);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002268
2269 /* Verify that the MMU has failed to be initialized */
2270 CHECK_TRUE(retval == -EINVAL);
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002271
2272 /* Restore the context initialized flag */
2273 ctx.cfg->initialized = true;
2274
2275 /* Force the architecture to report 4K granularity as not available */
2276 host_write_sysreg("id_aa64mmfr0_el1",
2277 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5U) |
2278 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2279 ID_AA64MMFR0_EL1_TGRAN4_NOT_SUPPORTED));
2280
2281 /* Try to initialize MMU for the given context */
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002282 retval = xlat_arch_setup_mmu_cfg(&ctx, &mmu_config);
Javier Almansa Sobrino2fa8abe2023-06-06 13:18:17 +01002283
2284 /* Verify that the MMU has failed to be initialized */
2285 CHECK_TRUE(retval == -EPERM);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002286
2287 /*
2288 * Force the architecture to report 4K granularity available without
2289 * support for LPA2 but with an PA size of more than 48 bits.
2290 * Note that this scenario should never happen on the architecture
2291 * however, the library still checks for this.
2292 */
2293 host_write_sysreg("id_aa64mmfr0_el1",
2294 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 6U) |
2295 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2296 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED));
2297
2298 /* Try to initialize MMU for the given context */
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002299 retval = xlat_arch_setup_mmu_cfg(&ctx, &mmu_config);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002300
2301 /* Verify that the MMU has failed to be initialized */
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002302 CHECK_TRUE(retval == -EPERM);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002303
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002304}
2305
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002306void xlat_arch_setup_mmu_cfg_tc3(void)
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002307{
2308 /***************************************************************
2309 * TEST CASE 3:
2310 *
2311 * Test xlat_arch_setup_mmu_cfg() with a NULL context.
2312 ***************************************************************/
2313
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002314 struct xlat_mmu_cfg mmu_config;
2315
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002316 test_helpers_expect_assert_fail(true);
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002317 (void)xlat_arch_setup_mmu_cfg(NULL, &mmu_config);
Javier Almansa Sobrino6cf9d8a2023-03-29 17:42:22 +01002318 test_helpers_fail_if_no_assert_failed();
2319}
2320
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002321void xlat_arch_setup_mmu_cfg_tc4(void)
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002322{
2323 struct xlat_ctx ctx;
2324 struct xlat_ctx_cfg cfg;
2325 struct xlat_ctx_tbls tbls;
2326 struct xlat_mmap_region init_mmap;
2327
2328 /***************************************************************
2329 * TEST CASE 4:
2330 *
2331 * Test xlat_arch_setup_mmu_cfg() with a context in which the
2332 * configuration is NULL.
2333 *
2334 * This test reuses xlat_get_llt_from_va_prepare_assertion()
2335 * in order to generate an initial valid context.
2336 ***************************************************************/
2337
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002338 struct xlat_mmu_cfg mmu_config;
2339
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002340 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
2341
2342 /* Force the context configuration to NULL */
2343 ctx.cfg = NULL;
2344
2345 test_helpers_expect_assert_fail(true);
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002346 (void)xlat_arch_setup_mmu_cfg(&ctx, &mmu_config);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002347 test_helpers_fail_if_no_assert_failed();
2348}
2349
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002350void xlat_arch_setup_mmu_cfg_tc5(void)
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002351{
2352 struct xlat_ctx ctx;
2353 struct xlat_ctx_cfg cfg;
2354 struct xlat_ctx_tbls tbls;
2355 struct xlat_mmap_region init_mmap;
2356
2357 /***************************************************************
2358 * TEST CASE 5:
2359 *
2360 * Test xlat_arch_setup_mmu_cfg() with a context in which the
2361 * 'tbls' structure is NULL.
2362 *
2363 * This test reuses xlat_get_llt_from_va_prepare_assertion()
2364 * in order to generate an initial valid context.
2365 ***************************************************************/
2366
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002367 struct xlat_mmu_cfg mmu_config;
2368
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002369 xlat_get_llt_from_va_prepare_assertion(&ctx, &cfg, &tbls, &init_mmap);
2370
2371 /* Force the context tables structure to NULL */
2372 ctx.tbls = NULL;
2373
2374 test_helpers_expect_assert_fail(true);
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002375 (void)xlat_arch_setup_mmu_cfg(&ctx, &mmu_config);
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002376 test_helpers_fail_if_no_assert_failed();
2377}
2378
Soby Mathew4714e232023-10-04 07:03:08 +01002379void xlat_arch_setup_mmu_cfg_tc6(void)
2380{
2381 struct xlat_ctx ctx;
2382 struct xlat_ctx_cfg cfg;
2383 struct xlat_ctx_tbls tbls;
2384 uintptr_t start_va, end_va;
2385 int retval;
2386 struct xlat_mmap_region init_mmap;
2387 uint64_t max_va_size = XLAT_TEST_MAX_VA_SIZE();
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002388 struct xlat_mmu_cfg mmu_config;
Soby Mathew4714e232023-10-04 07:03:08 +01002389
2390 /***************************************************************
2391 * TEST CASE 6:
2392 * Generate a valid translation context for one of the regions
2393 * and call xlat_arch_setup_mmu_cfg() with the MMU enabled.
2394 *
2395 ***************************************************************/
2396
2397 /* Clean the data structures */
2398 memset((void *)&ctx, 0, sizeof(struct xlat_ctx));
2399 memset((void *)&cfg, 0, sizeof(struct xlat_ctx_cfg));
2400 memset((void *)&tbls, 0, sizeof(struct xlat_ctx_tbls));
2401
2402 /* VA space boundaries */
2403 start_va = xlat_test_helpers_get_start_va(VA_LOW_REGION, max_va_size);
2404 end_va = start_va + max_va_size - 1UL;
2405
2406 /* Generate only a single mmap region for each region */
Mate Toth-Pal3f0a8ae2024-08-01 11:09:56 +02002407 xlat_test_helpers_rand_mmap_array(&init_mmap, 1U, start_va, end_va, true);
Soby Mathew4714e232023-10-04 07:03:08 +01002408
2409 retval = xlat_ctx_cfg_init(&cfg, VA_LOW_REGION, &init_mmap,
2410 1U, max_va_size);
2411 CHECK_TRUE(retval == 0);
2412
2413 retval = xlat_ctx_init(&ctx, &cfg, &tbls,
2414 xlat_test_helpers_tbls(),
2415 XLAT_TESTS_MAX_TABLES);
2416 CHECK_TRUE(retval == 0);
2417
2418 /* Force the MMU enablement */
2419 xlat_enable_mmu_el2();
2420
2421 test_helpers_expect_assert_fail(true);
2422
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002423 /* Initialize MMU config for the given context */
2424 retval = xlat_arch_setup_mmu_cfg(&ctx, &mmu_config);
2425 CHECK_TRUE(retval == 0);
Soby Mathew4714e232023-10-04 07:03:08 +01002426
Mate Toth-Paldb9c5e82024-08-01 11:05:58 +02002427 /* Try to write the MMU config for the given context */
2428 xlat_arch_write_mmu_cfg(&mmu_config);
2429
2430 test_helpers_fail_if_no_assert_failed();
2431}
2432
2433void xlat_arch_setup_mmu_cfg_tc7(void)
2434{
2435 /***************************************************************
2436 * TEST CASE 7:
2437 *
2438 * Test xlat_arch_setup_mmu_cfg() with a NULL config.
2439 ***************************************************************/
2440
2441 struct xlat_ctx ctx;
2442
2443 test_helpers_expect_assert_fail(true);
2444 (void)xlat_arch_setup_mmu_cfg(&ctx, NULL);
Soby Mathew4714e232023-10-04 07:03:08 +01002445 test_helpers_fail_if_no_assert_failed();
2446}
2447
Javier Almansa Sobrinocd599e22023-06-28 12:28:00 +01002448void xlat_get_oa_from_tte_tc1(void)
Javier Almansa Sobrino59f0ef62023-05-17 12:21:02 +01002449{
2450 uint64_t test_tte, val_addr, output_addr;
2451
2452 /***************************************************************
2453 * TEST CASE 1:
2454 *
2455 * Test xlat_get_oa_from_tte() with 4K granularity and with and
2456 * without LPA2 support.
2457 ***************************************************************/
2458
2459 /*
2460 * Generate a random TTE to test. We are not concerned about the
2461 * validity of the TTE or about any bitfield that is not part of
2462 * the output address, as xlat_get_oa_from_tte() is expected to
2463 * just ignore those.
2464 */
2465 test_tte = ~0ULL;
2466
2467 /* Test with FEAT_LPA2 available */
2468 host_write_sysreg("id_aa64mmfr0_el1",
2469 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 6UL) |
2470 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2471 ID_AA64MMFR0_EL1_TGRAN4_LPA2));
2472
2473 /* Generate the validation address from the test TTE */
2474 val_addr = test_tte & BIT_MASK_ULL(TTE_OA_BIT_49_LPA2, OA_SHIFT);
2475 val_addr |= INPLACE(OA_BITS_50_51, EXTRACT(TTE_OA_BITS_50_51, test_tte));
2476
2477 output_addr = xlat_get_oa_from_tte(test_tte);
2478
2479 CHECK_VERBOSE((val_addr == output_addr),
2480 "Test xlat_get_oa_from_tte, LPA2 supported: OA = %p - Expected = %p",
2481 (void *)output_addr, (void *)val_addr);
2482
2483 /* Repeat the test, by disabling support for FEAT_LPA2 this time */
2484 host_write_sysreg("id_aa64mmfr0_el1",
2485 INPLACE(ID_AA64MMFR0_EL1_PARANGE, 5U) |
2486 INPLACE(ID_AA64MMFR0_EL1_TGRAN4,
2487 ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED));
2488
2489 /* Generate the validation address */
2490 val_addr = test_tte & BIT_MASK_ULL(TTE_OA_MSB, OA_SHIFT);
2491
2492 output_addr = xlat_get_oa_from_tte(test_tte);
2493
2494 CHECK_VERBOSE((val_addr == output_addr),
2495 "Test xlat_get_oa_from_tte, LPA2 not supported: OA = %p - Expected = %p",
2496 (void *)output_addr, (void *)val_addr);
2497}