gpt: add GPT L1 alignment tests
L1 table alignment tests are added in this patch. The tests will
check whether a misaligned set of PAS regions is suitable to
initialize the L1 tables.
Signed-off-by: Juan Pablo Conde <juanpablo.conde@arm.com>
Co-developed-by: Kathleen Capella <kathleen.capella@arm.com>
Change-Id: I8bd0349806fe0eb714b32044172a091c2277fad5
diff --git a/tests/lib/gpt/test_gpt_utils.c b/tests/lib/gpt/test_gpt_utils.c
index f4c452c..aeed86f 100644
--- a/tests/lib/gpt/test_gpt_utils.c
+++ b/tests/lib/gpt/test_gpt_utils.c
@@ -284,15 +284,35 @@
return table;
}
+bool walk_l1_table (uintptr_t table, size_t l1_mem_size, bool l1_enabled, pas_region_t *pas_regions, unsigned int pas_count)
+{
+ int num_entries;
+ uint64_t * entry;
+
+ num_entries = l1_mem_size / L1_ENTRY_SIZE;
+ entry = (uint64_t *)table;
+
+ for (int i = 0; i < num_entries; i++) {
+ /* Check if valid granules descriptor or contiguous descriptor */
+ if(is_valid_granules_desc(entry[i]) == false) {
+ return false;
+ }else if (is_valid_contiguous_desc(entry[i]) == false) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
/*
* Creates a set of pass regions and returns the number of
* regions created and the number of l1 tables that need
* to be allocated.
*/
pas_regions_info_t create_pas_regions(pas_region_t *pas_regions,
- unsigned long int pps, unsigned long int pgs,
+ unsigned long int pps, unsigned long int pgs,
unsigned long int l0gptsz)
-{
+{
size_t size;
unsigned int attrs;
int num_l0_entries;
@@ -300,26 +320,20 @@
bool choose_entry_type = true;
int i = 0;
unsigned long int remaining_space = pps;
-
srand(time(NULL));
-
- pas_regions_info_t counts = {
+ pas_regions_info_t counts = {
.pas_count = 0,
.l1_table_count = 0
};
uintptr_t base_pa = 0x0;
-
num_l0_entries = pps/l0gptsz;
-
for (i = 0; i < num_l0_entries; ++i) {
bool entry_added = false;
pas_region_t new_pas_region;
-
if (choose_entry_type) {
entry_type = i % 2;
}
choose_entry_type = true;
-
/* Choose a GPI encoding for the entry */
attrs = GPI_OPTIONS[(int)(i % NUM_GPI_OPTIONS)];
@@ -366,7 +380,6 @@
counts.l1_table_count++;
entry_added = true;
}
-
if (entry_added) {
pas_regions[counts.pas_count] = new_pas_region;
base_pa += size;
@@ -374,6 +387,5 @@
remaining_space = pps - base_pa;
}
}
-
return counts;
}
diff --git a/tests/lib/gpt/test_gpt_utils.h b/tests/lib/gpt/test_gpt_utils.h
index b310f28..4e9995c 100644
--- a/tests/lib/gpt/test_gpt_utils.h
+++ b/tests/lib/gpt/test_gpt_utils.h
@@ -51,6 +51,8 @@
bool is_valid_granules_desc(uint64_t granules_desc);
bool is_valid_contiguous_desc(uint64_t contiguous_desc);
bool check_gpi_type(uint64_t gpi, unsigned int expected_type);
+bool walk_l1_table (uintptr_t table, size_t l1_mem_size, bool l1_enabled,
+ pas_region_t *pas_regions, unsigned int pas_count);
uintptr_t allocate_l0_table_mem(size_t l0_mem_size);
uintptr_t allocate_l1_table_mem(uintptr_t table, size_t l1_mem_size);
pas_regions_info_t create_pas_regions(pas_region_t *pas_regions,
diff --git a/tests/lib/gpt/test_tables.cpp b/tests/lib/gpt/test_tables.cpp
index 57e5700..55f59d0 100644
--- a/tests/lib/gpt/test_tables.cpp
+++ b/tests/lib/gpt/test_tables.cpp
@@ -382,3 +382,115 @@
FAIL("\n");
}
}
+
+/*
+ * TEST_GROUP: misaligned_l1_table
+ * Tests the behavior or wrongly aligned L1 tables
+ */
+TEST_GROUP(misaligned_l1_table) {
+ TEST_SETUP() {
+ int i = 0;
+ int j = 0;
+ int k = 0;
+
+ unsigned int num_l0_entries;
+ unsigned int num_l1_tables;
+ unsigned int init_pas_count;
+ unsigned int l1_table_count;
+
+ /* Enable MMU and data caches */
+ enable_mmu();
+
+ uintptr_t base_pa = 0x0;
+
+ /* Get PPS */
+ pps = pps_values[j];
+ pps_encoding = pps_encodings[j];
+
+ /* Set the mock PPS */
+ set_pps(pps_encoding);
+
+ /* Get L0GPTSZ */
+ l0gptsz = l0gptsz_values[i];
+
+ /* Set the mock L0 page size */
+ set_l0gptsz(l0gptsz_encodings[i]);
+
+ /* Get PGS */
+ pgs_encoding = pgs_encodings[k];
+
+ /* Set the mock PGS */
+ set_pgs((gpccr_pgs_e)pgs_encoding);
+
+ /* Allocate memory for L0 table */
+ l0_mem_size = pps >= l0gptsz ? (pps/l0gptsz) * L0_ENTRY_SIZE : L0_ENTRY_SIZE;
+
+ l0_table = allocate_l0_table_mem(l0_mem_size);
+
+ if (!l0_table)
+ FAIL("Unable to allocate L0 table\n");
+
+ pgs = SIZE_4KB;
+ pgs_encoding = GPCCR_PGS_4K;
+
+ num_l0_entries = l0_mem_size / L0_ENTRY_SIZE;
+
+ l1_table_count = pps/l0gptsz;
+
+ /* Calculate size for L1 tables */
+ l1_mem_size = ((l0gptsz / pgs) / 2) * l1_table_count;
+
+ /* Allocate space for L1 tables */
+ l1_table = allocate_l1_table_mem(l1_table, l1_mem_size);
+ if (!l1_table)
+ FAIL("Unable to allocate L1 table\n");
+ }
+
+ TEST_TEARDOWN() {
+ if (l0_table)
+ free((void *)l0_table);
+ if (l1_table)
+ free((void *)l1_table);
+ }
+
+ unsigned long int pps;
+ gpccr_pgs_e pgs_encoding;
+ size_t pgs;
+ gpccr_pps_e pps_encoding;
+ unsigned long l0gptsz;
+ gpccr_l0gptsz_e l0gptsz_encoding;
+ size_t l0_mem_size;
+ size_t l1_mem_size;
+ uintptr_t l0_table;
+ uintptr_t l1_table;
+};
+
+/*
+ * TEST: unaligned
+ * Tests whether a set of misaligned PAS regions can be used to
+ * initialize L1 tables.
+ */
+TEST(misaligned_l1_table, unaligned){
+ pas_region_t pas_regions[] = {
+ GPT_MAP_REGION_BLOCK(PAS_1_BASE, PAS_1_SIZE, PAS_1_GPI),
+ /* The granule base address is misaligned for this test.
+ * All granule regions are shifted one byte. */
+ GPT_MAP_REGION_GRANULE(PAS_2_BASE + 1, PAS_2_SIZE, PAS_2_GPI),
+ GPT_MAP_REGION_GRANULE(PAS_3_BASE + 1, PAS_3_SIZE, PAS_3_GPI),
+ GPT_MAP_REGION_GRANULE(PAS_4_BASE + 1, PAS_4_SIZE, PAS_4_GPI),
+ GPT_MAP_REGION_GRANULE(PAS_5_BASE + 1, PAS_5_SIZE, PAS_5_GPI),
+ GPT_MAP_REGION_GRANULE(PAS_6_BASE + 1, PAS_6_SIZE, PAS_6_GPI),
+ };
+ unsigned int pas_region_count = 6;
+
+ if (gpt_init_l0_tables(pps_encoding, l0_table, l0_mem_size) != 0){
+ printf("Failed to init l0 table for pps %lu, l0gptsz %lu", pps, l0gptsz);
+ FAIL("\n");
+ }
+ walk_l0_table(l0_table, l0_mem_size, false);
+ if (gpt_init_pas_l1_tables(pgs_encoding, l1_table, l1_mem_size, pas_regions, pas_region_count) == 0){
+ printf("Misaligned L1 test failed.\n");
+ FAIL("\n");
+ }
+}
+