mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-22 20:38:03 +00:00
Merge pull request #1900 from soby-mathew/sm/revert_xlat_changes
xlat_tables_v2: Revert recent changes to remove recursion
This commit is contained in:
commit
859cf9ea33
2 changed files with 151 additions and 339 deletions
|
@ -325,9 +325,8 @@ static action_t xlat_tables_unmap_region_action(const mmap_region_t *mm,
|
||||||
|
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function that writes to the translation tables and unmaps the
|
* Recursive function that writes to the translation tables and unmaps the
|
||||||
* specified region.
|
* specified region.
|
||||||
*/
|
*/
|
||||||
static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm,
|
static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm,
|
||||||
|
@ -338,137 +337,70 @@ static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm,
|
||||||
{
|
{
|
||||||
assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX));
|
assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX));
|
||||||
|
|
||||||
/*
|
uint64_t *subtable;
|
||||||
* data structure to track DESC_TABLE entry before iterate into subtable
|
uint64_t desc;
|
||||||
* of next translation level. it will be used to restore previous level
|
|
||||||
* after finish subtable iteration.
|
|
||||||
*/
|
|
||||||
struct desc_table_unmap {
|
|
||||||
uint64_t *table_base;
|
|
||||||
uintptr_t table_idx_va;
|
|
||||||
unsigned int idx;
|
|
||||||
} desc_tables[XLAT_TABLE_LEVEL_MAX + 1] = {
|
|
||||||
{NULL, 0U, XLAT_TABLE_ENTRIES}, };
|
|
||||||
|
|
||||||
unsigned int this_level = level;
|
|
||||||
uint64_t *this_base = table_base;
|
|
||||||
unsigned int max_entries = table_entries;
|
|
||||||
size_t level_size = XLAT_BLOCK_SIZE(this_level);
|
|
||||||
unsigned int table_idx;
|
|
||||||
uintptr_t table_idx_va;
|
uintptr_t table_idx_va;
|
||||||
|
uintptr_t table_idx_end_va; /* End VA of this entry */
|
||||||
|
|
||||||
uintptr_t region_end_va = mm->base_va + mm->size - 1U;
|
uintptr_t region_end_va = mm->base_va + mm->size - 1U;
|
||||||
|
|
||||||
|
unsigned int table_idx;
|
||||||
|
|
||||||
table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level);
|
table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level);
|
||||||
table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level);
|
table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level);
|
||||||
|
|
||||||
while (this_base != NULL) {
|
while (table_idx < table_entries) {
|
||||||
|
|
||||||
uint64_t desc;
|
table_idx_end_va = table_idx_va + XLAT_BLOCK_SIZE(level) - 1U;
|
||||||
uint64_t desc_type;
|
|
||||||
uintptr_t table_idx_end_va; /* End VA of this entry */
|
|
||||||
action_t action;
|
|
||||||
|
|
||||||
/* finish current xlat level iteration. */
|
desc = table_base[table_idx];
|
||||||
if (table_idx >= max_entries) {
|
uint64_t desc_type = desc & DESC_MASK;
|
||||||
if (this_level > ctx->base_level) {
|
|
||||||
xlat_table_dec_regions_count(ctx, this_base);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this_level > level) {
|
action_t action = xlat_tables_unmap_region_action(mm,
|
||||||
uint64_t *subtable;
|
table_idx_va, table_idx_end_va, level,
|
||||||
|
desc_type);
|
||||||
/* back from subtable iteration, restore
|
|
||||||
* previous DESC_TABLE entry.
|
|
||||||
*/
|
|
||||||
this_level--;
|
|
||||||
this_base = desc_tables[this_level].table_base;
|
|
||||||
table_idx = desc_tables[this_level].idx;
|
|
||||||
table_idx_va =
|
|
||||||
desc_tables[this_level].table_idx_va;
|
|
||||||
level_size = XLAT_BLOCK_SIZE(this_level);
|
|
||||||
|
|
||||||
if (this_level == level) {
|
|
||||||
max_entries = table_entries;
|
|
||||||
} else {
|
|
||||||
max_entries = XLAT_TABLE_ENTRIES;
|
|
||||||
}
|
|
||||||
|
|
||||||
desc = this_base[table_idx];
|
|
||||||
subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
|
|
||||||
/*
|
|
||||||
* If the subtable is now empty, remove its reference.
|
|
||||||
*/
|
|
||||||
if (xlat_table_is_empty(ctx, subtable)) {
|
|
||||||
this_base[table_idx] = INVALID_DESC;
|
|
||||||
xlat_arch_tlbi_va(table_idx_va,
|
|
||||||
ctx->xlat_regime);
|
|
||||||
}
|
|
||||||
table_idx++;
|
|
||||||
table_idx_va += level_size;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* reached end of top level, exit.*/
|
|
||||||
this_base = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If reached the end of the region, stop iterating entries in
|
|
||||||
* current xlat level.
|
|
||||||
*/
|
|
||||||
if (region_end_va <= table_idx_va) {
|
|
||||||
table_idx = max_entries;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
table_idx_end_va = table_idx_va + XLAT_BLOCK_SIZE(this_level) - 1U;
|
|
||||||
|
|
||||||
desc = this_base[table_idx];
|
|
||||||
desc_type = desc & DESC_MASK;
|
|
||||||
|
|
||||||
action = xlat_tables_unmap_region_action(mm, table_idx_va,
|
|
||||||
table_idx_end_va,
|
|
||||||
this_level,
|
|
||||||
desc_type);
|
|
||||||
|
|
||||||
if (action == ACTION_WRITE_BLOCK_ENTRY) {
|
if (action == ACTION_WRITE_BLOCK_ENTRY) {
|
||||||
this_base[table_idx] = INVALID_DESC;
|
|
||||||
|
table_base[table_idx] = INVALID_DESC;
|
||||||
xlat_arch_tlbi_va(table_idx_va, ctx->xlat_regime);
|
xlat_arch_tlbi_va(table_idx_va, ctx->xlat_regime);
|
||||||
|
|
||||||
table_idx++;
|
|
||||||
table_idx_va += level_size;
|
|
||||||
} else if (action == ACTION_RECURSE_INTO_TABLE) {
|
} else if (action == ACTION_RECURSE_INTO_TABLE) {
|
||||||
|
|
||||||
uint64_t *subtable;
|
|
||||||
uintptr_t base_va;
|
|
||||||
|
|
||||||
subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
|
subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
|
||||||
|
|
||||||
desc_tables[this_level].table_base = this_base;
|
/* Recurse to write into subtable */
|
||||||
desc_tables[this_level].table_idx_va = table_idx_va;
|
xlat_tables_unmap_region(ctx, mm, table_idx_va,
|
||||||
base_va = table_idx_va;
|
subtable, XLAT_TABLE_ENTRIES,
|
||||||
desc_tables[this_level].idx = table_idx;
|
level + 1U);
|
||||||
|
#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
|
||||||
|
xlat_clean_dcache_range((uintptr_t)subtable,
|
||||||
|
XLAT_TABLE_ENTRIES * sizeof(uint64_t));
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* If the subtable is now empty, remove its reference.
|
||||||
|
*/
|
||||||
|
if (xlat_table_is_empty(ctx, subtable)) {
|
||||||
|
table_base[table_idx] = INVALID_DESC;
|
||||||
|
xlat_arch_tlbi_va(table_idx_va,
|
||||||
|
ctx->xlat_regime);
|
||||||
|
}
|
||||||
|
|
||||||
this_base = subtable;
|
|
||||||
this_level++;
|
|
||||||
|
|
||||||
max_entries = XLAT_TABLE_ENTRIES;
|
|
||||||
level_size = XLAT_BLOCK_SIZE(this_level);
|
|
||||||
|
|
||||||
table_idx_va = xlat_tables_find_start_va(mm,
|
|
||||||
base_va, this_level);
|
|
||||||
table_idx = xlat_tables_va_to_index(base_va,
|
|
||||||
table_idx_va, this_level);
|
|
||||||
} else {
|
} else {
|
||||||
assert(action == ACTION_NONE);
|
assert(action == ACTION_NONE);
|
||||||
|
|
||||||
table_idx++;
|
|
||||||
table_idx_va += level_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table_idx++;
|
||||||
|
table_idx_va += XLAT_BLOCK_SIZE(level);
|
||||||
|
|
||||||
|
/* If reached the end of the region, exit */
|
||||||
|
if (region_end_va <= table_idx_va)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (level > ctx->base_level)
|
||||||
|
xlat_table_dec_regions_count(ctx, table_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* PLAT_XLAT_TABLES_DYNAMIC */
|
#endif /* PLAT_XLAT_TABLES_DYNAMIC */
|
||||||
|
@ -605,169 +537,105 @@ static action_t xlat_tables_map_region_action(const mmap_region_t *mm,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function that writes to the translation tables and maps the
|
* Recursive function that writes to the translation tables and maps the
|
||||||
* specified region. On success, it returns the VA of the last byte that was
|
* specified region. On success, it returns the VA of the last byte that was
|
||||||
* successfully mapped. On error, it returns the VA of the next entry that
|
* successfully mapped. On error, it returns the VA of the next entry that
|
||||||
* should have been mapped.
|
* should have been mapped.
|
||||||
*/
|
*/
|
||||||
static uintptr_t xlat_tables_map_region(xlat_ctx_t *ctx, mmap_region_t *mm,
|
static uintptr_t xlat_tables_map_region(xlat_ctx_t *ctx, mmap_region_t *mm,
|
||||||
const uintptr_t table_base_va,
|
uintptr_t table_base_va,
|
||||||
uint64_t *const table_base,
|
uint64_t *const table_base,
|
||||||
unsigned int table_entries,
|
unsigned int table_entries,
|
||||||
unsigned int level)
|
unsigned int level)
|
||||||
{
|
{
|
||||||
|
|
||||||
assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX));
|
assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX));
|
||||||
|
|
||||||
/*
|
|
||||||
* data structure to track DESC_TABLE entry before iterate into subtable
|
|
||||||
* of next translation level. it will be used to restore previous level
|
|
||||||
* after finish subtable iteration.
|
|
||||||
*/
|
|
||||||
struct desc_table_map {
|
|
||||||
uint64_t *table_base;
|
|
||||||
uintptr_t table_idx_va;
|
|
||||||
unsigned int idx;
|
|
||||||
} desc_tables[XLAT_TABLE_LEVEL_MAX + 1] = {
|
|
||||||
{NULL, 0U, XLAT_TABLE_ENTRIES}, };
|
|
||||||
|
|
||||||
unsigned int this_level = level;
|
|
||||||
uint64_t *this_base = table_base;
|
|
||||||
unsigned int max_entries = table_entries;
|
|
||||||
size_t level_size = XLAT_BLOCK_SIZE(this_level);
|
|
||||||
uintptr_t mm_end_va = mm->base_va + mm->size - 1U;
|
uintptr_t mm_end_va = mm->base_va + mm->size - 1U;
|
||||||
|
|
||||||
uintptr_t table_idx_va;
|
uintptr_t table_idx_va;
|
||||||
|
unsigned long long table_idx_pa;
|
||||||
|
|
||||||
|
uint64_t *subtable;
|
||||||
|
uint64_t desc;
|
||||||
|
|
||||||
unsigned int table_idx;
|
unsigned int table_idx;
|
||||||
|
|
||||||
table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level);
|
table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level);
|
||||||
table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level);
|
table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level);
|
||||||
|
|
||||||
while (this_base != NULL) {
|
#if PLAT_XLAT_TABLES_DYNAMIC
|
||||||
|
if (level > ctx->base_level)
|
||||||
uint64_t desc;
|
xlat_table_inc_regions_count(ctx, table_base);
|
||||||
uint64_t desc_type;
|
|
||||||
unsigned long long table_idx_pa;
|
|
||||||
action_t action;
|
|
||||||
|
|
||||||
/* finish current xlat level iteration. */
|
|
||||||
if (table_idx >= max_entries) {
|
|
||||||
if (this_level <= level) {
|
|
||||||
this_base = NULL;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* back from subtable iteration, restore
|
|
||||||
* previous DESC_TABLE entry.
|
|
||||||
*/
|
|
||||||
this_level--;
|
|
||||||
level_size = XLAT_BLOCK_SIZE(this_level);
|
|
||||||
this_base = desc_tables[this_level].table_base;
|
|
||||||
table_idx = desc_tables[this_level].idx;
|
|
||||||
if (this_level == level) {
|
|
||||||
max_entries = table_entries;
|
|
||||||
} else {
|
|
||||||
max_entries = XLAT_TABLE_ENTRIES;
|
|
||||||
}
|
|
||||||
#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
|
|
||||||
uintptr_t subtable;
|
|
||||||
desc = this_base[table_idx];
|
|
||||||
subtable = (uintptr_t)(desc & TABLE_ADDR_MASK);
|
|
||||||
xlat_clean_dcache_range(subtable,
|
|
||||||
XLAT_TABLE_ENTRIES * sizeof(uint64_t));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
table_idx++;
|
while (table_idx < table_entries) {
|
||||||
table_idx_va =
|
|
||||||
desc_tables[this_level].table_idx_va +
|
|
||||||
level_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
desc = this_base[table_idx];
|
desc = table_base[table_idx];
|
||||||
desc_type = desc & DESC_MASK;
|
|
||||||
|
|
||||||
table_idx_pa = mm->base_pa + table_idx_va - mm->base_va;
|
table_idx_pa = mm->base_pa + table_idx_va - mm->base_va;
|
||||||
|
|
||||||
/* If reached the end of the region, simply exit since we
|
action_t action = xlat_tables_map_region_action(mm,
|
||||||
* already write all BLOCK entries and create all required
|
(uint32_t)(desc & DESC_MASK), table_idx_pa,
|
||||||
* subtables.
|
table_idx_va, level);
|
||||||
*/
|
|
||||||
if (mm_end_va <= table_idx_va) {
|
|
||||||
this_base = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
action = xlat_tables_map_region_action(mm, desc_type,
|
|
||||||
table_idx_pa, table_idx_va, this_level);
|
|
||||||
|
|
||||||
if (action == ACTION_WRITE_BLOCK_ENTRY) {
|
if (action == ACTION_WRITE_BLOCK_ENTRY) {
|
||||||
this_base[table_idx] = xlat_desc(ctx, mm->attr,
|
|
||||||
table_idx_pa, this_level);
|
table_base[table_idx] =
|
||||||
table_idx++;
|
xlat_desc(ctx, (uint32_t)mm->attr, table_idx_pa,
|
||||||
table_idx_va += level_size;
|
level);
|
||||||
|
|
||||||
} else if (action == ACTION_CREATE_NEW_TABLE) {
|
} else if (action == ACTION_CREATE_NEW_TABLE) {
|
||||||
|
uintptr_t end_va;
|
||||||
|
|
||||||
uintptr_t base_va;
|
subtable = xlat_table_get_empty(ctx);
|
||||||
|
|
||||||
uint64_t *subtable = xlat_table_get_empty(ctx);
|
|
||||||
if (subtable == NULL) {
|
if (subtable == NULL) {
|
||||||
/* Not enough free tables to map this region. */
|
/* Not enough free tables to map this region */
|
||||||
return table_idx_va;
|
return table_idx_va;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Point to new subtable from this one. */
|
/* Point to new subtable from this one. */
|
||||||
this_base[table_idx] = TABLE_DESC | (unsigned long)subtable;
|
table_base[table_idx] = TABLE_DESC | (unsigned long)subtable;
|
||||||
|
|
||||||
desc_tables[this_level].table_base = this_base;
|
/* Recurse to write into subtable */
|
||||||
desc_tables[this_level].table_idx_va = table_idx_va;
|
end_va = xlat_tables_map_region(ctx, mm, table_idx_va,
|
||||||
desc_tables[this_level].idx = table_idx;
|
subtable, XLAT_TABLE_ENTRIES,
|
||||||
base_va = table_idx_va;
|
level + 1U);
|
||||||
|
#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
|
||||||
this_level++;
|
xlat_clean_dcache_range((uintptr_t)subtable,
|
||||||
this_base = subtable;
|
XLAT_TABLE_ENTRIES * sizeof(uint64_t));
|
||||||
level_size = XLAT_BLOCK_SIZE(this_level);
|
|
||||||
table_idx_va = xlat_tables_find_start_va(mm, base_va,
|
|
||||||
this_level);
|
|
||||||
table_idx = xlat_tables_va_to_index(base_va,
|
|
||||||
table_idx_va, this_level);
|
|
||||||
max_entries = XLAT_TABLE_ENTRIES;
|
|
||||||
|
|
||||||
#if PLAT_XLAT_TABLES_DYNAMIC
|
|
||||||
if (this_level > ctx->base_level) {
|
|
||||||
xlat_table_inc_regions_count(ctx, subtable);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
if (end_va !=
|
||||||
|
(table_idx_va + XLAT_BLOCK_SIZE(level) - 1U))
|
||||||
|
return end_va;
|
||||||
|
|
||||||
} else if (action == ACTION_RECURSE_INTO_TABLE) {
|
} else if (action == ACTION_RECURSE_INTO_TABLE) {
|
||||||
|
uintptr_t end_va;
|
||||||
|
|
||||||
uintptr_t base_va;
|
subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
|
||||||
uint64_t *subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
|
/* Recurse to write into subtable */
|
||||||
|
end_va = xlat_tables_map_region(ctx, mm, table_idx_va,
|
||||||
desc_tables[this_level].table_base = this_base;
|
subtable, XLAT_TABLE_ENTRIES,
|
||||||
desc_tables[this_level].table_idx_va = table_idx_va;
|
level + 1U);
|
||||||
desc_tables[this_level].idx = table_idx;
|
#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
|
||||||
base_va = table_idx_va;
|
xlat_clean_dcache_range((uintptr_t)subtable,
|
||||||
|
XLAT_TABLE_ENTRIES * sizeof(uint64_t));
|
||||||
this_level++;
|
|
||||||
level_size = XLAT_BLOCK_SIZE(this_level);
|
|
||||||
table_idx_va = xlat_tables_find_start_va(mm, base_va,
|
|
||||||
this_level);
|
|
||||||
table_idx = xlat_tables_va_to_index(base_va,
|
|
||||||
table_idx_va, this_level);
|
|
||||||
this_base = subtable;
|
|
||||||
max_entries = XLAT_TABLE_ENTRIES;
|
|
||||||
|
|
||||||
#if PLAT_XLAT_TABLES_DYNAMIC
|
|
||||||
if (this_level > ctx->base_level) {
|
|
||||||
xlat_table_inc_regions_count(ctx, subtable);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
if (end_va !=
|
||||||
|
(table_idx_va + XLAT_BLOCK_SIZE(level) - 1U))
|
||||||
|
return end_va;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
assert(action == ACTION_NONE);
|
assert(action == ACTION_NONE);
|
||||||
table_idx++;
|
|
||||||
table_idx_va += level_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table_idx++;
|
||||||
|
table_idx_va += XLAT_BLOCK_SIZE(level);
|
||||||
|
|
||||||
|
/* If reached the end of the region, exit */
|
||||||
|
if (mm_end_va <= table_idx_va)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return table_idx_va - 1U;
|
return table_idx_va - 1U;
|
||||||
|
|
|
@ -109,7 +109,7 @@ static const char *invalid_descriptors_ommited =
|
||||||
"%s(%d invalid descriptors omitted)\n";
|
"%s(%d invalid descriptors omitted)\n";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function that reads the translation tables passed as an argument
|
* Recursive function that reads the translation tables passed as an argument
|
||||||
* and prints their status.
|
* and prints their status.
|
||||||
*/
|
*/
|
||||||
static void xlat_tables_print_internal(xlat_ctx_t *ctx, uintptr_t table_base_va,
|
static void xlat_tables_print_internal(xlat_ctx_t *ctx, uintptr_t table_base_va,
|
||||||
|
@ -118,23 +118,10 @@ static void xlat_tables_print_internal(xlat_ctx_t *ctx, uintptr_t table_base_va,
|
||||||
{
|
{
|
||||||
assert(level <= XLAT_TABLE_LEVEL_MAX);
|
assert(level <= XLAT_TABLE_LEVEL_MAX);
|
||||||
|
|
||||||
/*
|
uint64_t desc;
|
||||||
* data structure to track DESC_TABLE entry before iterate into subtable
|
|
||||||
* of next translation level. it will be restored after return from
|
|
||||||
* subtable iteration.
|
|
||||||
*/
|
|
||||||
struct desc_table {
|
|
||||||
const uint64_t *table_base;
|
|
||||||
uintptr_t table_idx_va;
|
|
||||||
unsigned int idx;
|
|
||||||
} desc_tables[XLAT_TABLE_LEVEL_MAX + 1] = {
|
|
||||||
{NULL, 0U, XLAT_TABLE_ENTRIES}, };
|
|
||||||
unsigned int this_level = level;
|
|
||||||
const uint64_t *this_base = table_base;
|
|
||||||
unsigned int max_entries = table_entries;
|
|
||||||
size_t level_size = XLAT_BLOCK_SIZE(this_level);
|
|
||||||
unsigned int table_idx = 0U;
|
|
||||||
uintptr_t table_idx_va = table_base_va;
|
uintptr_t table_idx_va = table_base_va;
|
||||||
|
unsigned int table_idx = 0U;
|
||||||
|
size_t level_size = XLAT_BLOCK_SIZE(level);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep track of how many invalid descriptors are counted in a row.
|
* Keep track of how many invalid descriptors are counted in a row.
|
||||||
|
@ -144,110 +131,67 @@ static void xlat_tables_print_internal(xlat_ctx_t *ctx, uintptr_t table_base_va,
|
||||||
*/
|
*/
|
||||||
int invalid_row_count = 0;
|
int invalid_row_count = 0;
|
||||||
|
|
||||||
while (this_base != NULL) {
|
while (table_idx < table_entries) {
|
||||||
/* finish current xlat level */
|
|
||||||
if (table_idx >= max_entries) {
|
desc = table_base[table_idx];
|
||||||
|
|
||||||
|
if ((desc & DESC_MASK) == INVALID_DESC) {
|
||||||
|
|
||||||
|
if (invalid_row_count == 0) {
|
||||||
|
printf("%sVA:0x%lx size:0x%zx\n",
|
||||||
|
level_spacers[level],
|
||||||
|
table_idx_va, level_size);
|
||||||
|
}
|
||||||
|
invalid_row_count++;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
if (invalid_row_count > 1) {
|
if (invalid_row_count > 1) {
|
||||||
printf(invalid_descriptors_ommited,
|
printf(invalid_descriptors_ommited,
|
||||||
level_spacers[this_level],
|
level_spacers[level],
|
||||||
invalid_row_count - 1);
|
invalid_row_count - 1);
|
||||||
}
|
}
|
||||||
invalid_row_count = 0;
|
invalid_row_count = 0;
|
||||||
|
|
||||||
/* no parent level to iterate. */
|
/*
|
||||||
if (this_level <= level) {
|
* Check if this is a table or a block. Tables are only
|
||||||
this_base = NULL;
|
* allowed in levels other than 3, but DESC_PAGE has the
|
||||||
table_idx = max_entries + 1;
|
* same value as DESC_TABLE, so we need to check.
|
||||||
} else {
|
*/
|
||||||
/* retore previous DESC_TABLE entry and start
|
if (((desc & DESC_MASK) == TABLE_DESC) &&
|
||||||
* to iterate.
|
(level < XLAT_TABLE_LEVEL_MAX)) {
|
||||||
*/
|
|
||||||
this_level--;
|
|
||||||
level_size = XLAT_BLOCK_SIZE(this_level);
|
|
||||||
this_base = desc_tables[this_level].table_base;
|
|
||||||
table_idx = desc_tables[this_level].idx;
|
|
||||||
table_idx_va =
|
|
||||||
desc_tables[this_level].table_idx_va;
|
|
||||||
if (this_level == level) {
|
|
||||||
max_entries = table_entries;
|
|
||||||
} else {
|
|
||||||
max_entries = XLAT_TABLE_ENTRIES;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(this_base != NULL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
uint64_t desc = this_base[table_idx];
|
|
||||||
|
|
||||||
if ((desc & DESC_MASK) == INVALID_DESC) {
|
|
||||||
if (invalid_row_count == 0) {
|
|
||||||
printf("%sVA:0x%lx size:0x%zx\n",
|
|
||||||
level_spacers[this_level],
|
|
||||||
table_idx_va, level_size);
|
|
||||||
}
|
|
||||||
invalid_row_count++;
|
|
||||||
table_idx++;
|
|
||||||
table_idx_va += level_size;
|
|
||||||
} else {
|
|
||||||
if (invalid_row_count > 1) {
|
|
||||||
printf(invalid_descriptors_ommited,
|
|
||||||
level_spacers[this_level],
|
|
||||||
invalid_row_count - 1);
|
|
||||||
}
|
|
||||||
invalid_row_count = 0;
|
|
||||||
/*
|
/*
|
||||||
* Check if this is a table or a block. Tables
|
* Do not print any PA for a table descriptor,
|
||||||
* are only allowed in levels other than 3, but
|
* as it doesn't directly map physical memory
|
||||||
* DESC_PAGE has the same value as DESC_TABLE,
|
* but instead points to the next translation
|
||||||
* so we need to check.
|
* table in the translation table walk.
|
||||||
*/
|
*/
|
||||||
|
printf("%sVA:0x%lx size:0x%zx\n",
|
||||||
|
level_spacers[level],
|
||||||
|
table_idx_va, level_size);
|
||||||
|
|
||||||
if (((desc & DESC_MASK) == TABLE_DESC) &&
|
uintptr_t addr_inner = desc & TABLE_ADDR_MASK;
|
||||||
(this_level < XLAT_TABLE_LEVEL_MAX)) {
|
|
||||||
uintptr_t addr_inner;
|
|
||||||
|
|
||||||
/*
|
xlat_tables_print_internal(ctx, table_idx_va,
|
||||||
* Do not print any PA for a table
|
(uint64_t *)addr_inner,
|
||||||
* descriptor, as it doesn't directly
|
XLAT_TABLE_ENTRIES, level + 1U);
|
||||||
* map physical memory but instead
|
} else {
|
||||||
* points to the next translation
|
printf("%sVA:0x%lx PA:0x%llx size:0x%zx ",
|
||||||
* table in the translation table walk.
|
level_spacers[level], table_idx_va,
|
||||||
*/
|
(uint64_t)(desc & TABLE_ADDR_MASK),
|
||||||
printf("%sVA:0x%lx size:0x%zx\n",
|
level_size);
|
||||||
level_spacers[this_level],
|
xlat_desc_print(ctx, desc);
|
||||||
table_idx_va, level_size);
|
printf("\n");
|
||||||
|
|
||||||
addr_inner = desc & TABLE_ADDR_MASK;
|
|
||||||
/* save current xlat level */
|
|
||||||
desc_tables[this_level].table_base =
|
|
||||||
this_base;
|
|
||||||
desc_tables[this_level].idx =
|
|
||||||
table_idx + 1;
|
|
||||||
desc_tables[this_level].table_idx_va =
|
|
||||||
table_idx_va + level_size;
|
|
||||||
|
|
||||||
/* start iterating next level entries */
|
|
||||||
this_base = (uint64_t *)addr_inner;
|
|
||||||
max_entries = XLAT_TABLE_ENTRIES;
|
|
||||||
this_level++;
|
|
||||||
level_size =
|
|
||||||
XLAT_BLOCK_SIZE(this_level);
|
|
||||||
table_idx = 0U;
|
|
||||||
} else {
|
|
||||||
printf("%sVA:0x%lx PA:0x%llx size:0x%zx ",
|
|
||||||
level_spacers[this_level],
|
|
||||||
table_idx_va,
|
|
||||||
(uint64_t)(desc & TABLE_ADDR_MASK),
|
|
||||||
level_size);
|
|
||||||
xlat_desc_print(ctx, desc);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
table_idx++;
|
|
||||||
table_idx_va += level_size;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table_idx++;
|
||||||
|
table_idx_va += level_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invalid_row_count > 1) {
|
||||||
|
printf(invalid_descriptors_ommited,
|
||||||
|
level_spacers[level], invalid_row_count - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue